From 622305b0d3f854f75af8f88ade3fcc02e9d28b0d Mon Sep 17 00:00:00 2001 From: ThibaultBee <37510686+ThibaultBee@users.noreply.github.com> Date: Thu, 23 May 2024 11:03:15 +0200 Subject: [PATCH] feat(*): introducing a unique streamer not dependent of the endpoint --- DEVELOPER_README.md | 129 +++++++--- README.md | 87 ++++--- core/build.gradle | 3 + ...reamerTest.kt => AudioOnlyStreamerTest.kt} | 33 +-- .../testcases/AudioOnlyStreamerTestCase.kt | 115 ++++----- .../testcases/CameraStreamerTestCase.kt | 115 ++++----- .../streamer/testcases/StreamerTestCase.kt | 136 ++++------ .../utils/{AndroidUtils.kt => DataUtils.kt} | 18 +- .../streampack/utils/FileUtils.kt} | 23 +- core/src/main/AndroidManifest.xml | 3 - .../streampack/data/AudioConfig.kt | 4 +- .../thibaultbee/streampack/data/Config.kt | 4 +- .../streampack/data/VideoConfig.kt | 4 +- .../data/mediadescriptor/MediaDescriptor.kt | 8 + .../mediadescriptor/RtmpMediaDescriptor.kt | 30 ++- .../mediadescriptor/SrtMediaDescriptor.kt | 99 +++++--- .../mediadescriptor/UriMediaDescriptor.kt | 22 ++ .../internal/endpoints/DynamicEndpoint.kt | 170 +++++++++++++ .../internal/endpoints/IEndpoint.kt | 32 ++- .../internal/endpoints/MediaContainerType.kt | 35 +++ .../internal/endpoints/MediaMuxerEndpoint.kt | 111 ++++++--- .../internal/endpoints/MediaSinkType.kt | 33 +++ .../endpoints/composites/CompositeEndpoint.kt | 52 ++-- .../composites/CompositeEndpoints.kt | 83 +++++++ .../ConnectableCompositeEndpoint.kt | 42 ---- .../composites/FileCompositeEndpoint.kt | 47 ---- .../composites/ICompositeEndpoint.kt | 4 +- .../{ => composites}/muxers/IMuxer.kt | 6 +- .../{ => composites}/muxers/flv/FlvMuxer.kt | 26 +- .../muxers/flv/FlvMuxerInfo.kt | 21 +- .../muxers/flv/amf/AmfParameter.kt | 12 +- .../muxers/flv/amf/containers/AmfContainer.kt | 6 +- .../muxers/flv/amf/containers/AmfEcmaArray.kt | 8 +- .../muxers/flv/amf/containers/AmfObject.kt | 6 +- .../muxers/flv/amf/primitives/AmfBoolean.kt | 6 +- .../muxers/flv/amf/primitives/AmfInt16.kt | 4 +- .../muxers/flv/amf/primitives/AmfInt24.kt | 4 +- .../muxers/flv/amf/primitives/AmfInt32.kt | 4 +- .../flv/amf/primitives/AmfNamedParameter.kt | 4 +- .../muxers/flv/amf/primitives/AmfNull.kt | 6 +- .../muxers/flv/amf/primitives/AmfNumber.kt | 6 +- .../muxers/flv/amf/primitives/AmfString.kt | 6 +- .../muxers/flv/tags/AVTagsFactory.kt | 6 +- .../muxers/flv/tags/AudioTag.kt | 2 +- .../muxers/flv/tags/FlvHeader.kt | 2 +- .../muxers/flv/tags/FlvTag.kt | 2 +- .../muxers/flv/tags/OnMetadata.kt | 10 +- .../muxers/flv/tags/video/ExtendedVideoTag.kt | 6 +- .../muxers/flv/tags/video/VideoTag.kt | 6 +- .../muxers/flv/tags/video/VideoTagFactory.kt | 4 +- .../{ => composites}/muxers/mp4/MP4Muxer.kt | 26 +- .../muxers/mp4/MP4MuxerInfo.kt | 4 +- .../mp4/boxes/AV1CodecConfigurationBox.kt | 2 +- .../muxers/mp4/boxes/AVCConfigurationBox.kt | 2 +- .../muxers/mp4/boxes/BitRateBox.kt | 2 +- .../{ => composites}/muxers/mp4/boxes/Box.kt | 2 +- .../muxers/mp4/boxes/ChunkOffsetBox.kt | 2 +- .../muxers/mp4/boxes/CleanApertureBox.kt | 2 +- .../muxers/mp4/boxes/DataEntryBox.kt | 2 +- .../muxers/mp4/boxes/DataInformationBox.kt | 2 +- .../muxers/mp4/boxes/DataReferenceBox.kt | 2 +- .../muxers/mp4/boxes/ESDSBox.kt | 2 +- .../muxers/mp4/boxes/FileTypeBox.kt | 2 +- .../muxers/mp4/boxes/HEVCConfigurationBox.kt | 2 +- .../muxers/mp4/boxes/HandlerBox.kt | 2 +- .../muxers/mp4/boxes/MediaBox.kt | 2 +- .../muxers/mp4/boxes/MediaDataBox.kt | 2 +- .../muxers/mp4/boxes/MediaHeaderBox.kt | 4 +- .../muxers/mp4/boxes/MediaInformationBox.kt | 2 +- .../muxers/mp4/boxes/MovieBox.kt | 2 +- .../muxers/mp4/boxes/MovieExtendsBox.kt | 2 +- .../muxers/mp4/boxes/MovieFragmentBox.kt | 2 +- .../mp4/boxes/MovieFragmentHeaderBox.kt | 2 +- .../mp4/boxes/MovieFragmentRandomAccessBox.kt | 2 +- .../MovieFragmentRandomAccessOffsetBox.kt | 2 +- .../muxers/mp4/boxes/MovieHeaderBox.kt | 4 +- .../muxers/mp4/boxes/NullMediaHeaderBox.kt | 2 +- .../muxers/mp4/boxes/OpusSpecificBox.kt | 2 +- .../muxers/mp4/boxes/PixelAspectRatioBox.kt | 2 +- .../muxers/mp4/boxes/SampleDescriptionBox.kt | 2 +- .../muxers/mp4/boxes/SampleEntry.kt | 2 +- .../muxers/mp4/boxes/SampleSizeBox.kt | 2 +- .../muxers/mp4/boxes/SampleTableBox.kt | 2 +- .../muxers/mp4/boxes/SampleToChunkBox.kt | 2 +- .../muxers/mp4/boxes/SyncSampleBox.kt | 2 +- .../muxers/mp4/boxes/TimeToSampleBox.kt | 2 +- .../muxers/mp4/boxes/TrackBox.kt | 2 +- .../muxers/mp4/boxes/TrackExtendsBox.kt | 6 +- .../TrackFragmentBaseMediaDecodeTimeBox.kt | 2 +- .../muxers/mp4/boxes/TrackFragmentBox.kt | 2 +- .../mp4/boxes/TrackFragmentHeaderBox.kt | 6 +- .../mp4/boxes/TrackFragmentRandomAccessBox.kt | 2 +- .../muxers/mp4/boxes/TrackHeaderBox.kt | 4 +- .../muxers/mp4/boxes/TrackRunBox.kt | 6 +- .../muxers/mp4/boxes/TypeMediaHeaderBox.kt | 2 +- .../mp4/boxes/VPCodecConfigurationBox.kt | 2 +- .../muxers/mp4/models/Chunk.kt | 2 +- .../muxers/mp4/models/MovieBoxFactory.kt | 4 +- .../muxers/mp4/models/SampleFlags.kt | 2 +- .../muxers/mp4/models/Segment.kt | 4 +- .../muxers/mp4/models/Segmenter.kt | 2 +- .../muxers/mp4/models/SegmenterFactory.kt | 2 +- .../muxers/mp4/models/Track.kt | 2 +- .../muxers/mp4/models/TrackChunks.kt | 70 +++--- .../muxers/mp4/utils/ConfigExtensions.kt | 10 +- .../muxers/mp4/utils/TimeUtils.kt | 2 +- .../{ => composites}/muxers/ts/README.md | 0 .../{ => composites}/muxers/ts/TSMuxer.kt | 39 +-- .../{ => composites}/muxers/ts/TSMuxerInfo.kt | 13 +- .../muxers/ts/data/ITSElement.kt | 2 +- .../muxers/ts/data/Service.kt | 6 +- .../{ => composites}/muxers/ts/data/Stream.kt | 2 +- .../muxers/ts/data/TSServiceInfo.kt} | 9 +- .../muxers/ts/descriptors/AdaptationField.kt | 6 +- .../{ => composites}/muxers/ts/packets/Pat.kt | 10 +- .../{ => composites}/muxers/ts/packets/Pes.kt | 12 +- .../muxers/ts/packets/PesHeader.kt | 6 +- .../{ => composites}/muxers/ts/packets/Pmt.kt | 12 +- .../{ => composites}/muxers/ts/packets/Psi.kt | 8 +- .../{ => composites}/muxers/ts/packets/Sdt.kt | 10 +- .../{ => composites}/muxers/ts/packets/TS.kt | 10 +- .../muxers/ts/packets/TableHeader.kt | 4 +- .../{ => composites}/muxers/ts/utils/CRC32.kt | 2 +- .../muxers/ts/utils/MuxerConst.kt | 2 +- .../muxers/ts/utils/TSConst.kt | 2 +- .../muxers/ts/utils/TSOutputCallback.kt | 6 +- .../endpoints/composites/sinks/ContentSink.kt | 79 ++++++ .../{ => composites}/sinks/FakeSink.kt | 29 ++- .../endpoints/composites/sinks/FileSink.kt | 77 ++++++ .../{ => composites}/sinks/ILiveSink.kt | 22 +- .../endpoints/{ => composites}/sinks/ISink.kt | 24 +- .../composites/sinks/SinkConfiguration.kt} | 17 +- .../internal/endpoints/sinks/FileSink.kt | 71 ------ .../internal/endpoints/sinks/IFileSink.kt | 39 --- .../internal/events/EventHandler.kt | 51 ---- .../internal/interfaces/Streamable.kt | 7 + .../sources/video/camera/CameraSettings.kt | 4 +- .../sources/video/screen/ScreenSource.kt | 26 +- .../utils/extensions/ContextExtensions.kt | 10 - .../listeners/OnConnectionListener.kt | 12 - ...treamer.kt => DefaultAudioOnlyStreamer.kt} | 13 +- ...raStreamer.kt => DefaultCameraStreamer.kt} | 48 +++- ...er.kt => DefaultScreenRecorderStreamer.kt} | 28 ++- .../BaseStreamer.kt => DefaultStreamer.kt} | 146 ++++++++--- .../file/AudioOnlyFlvFileStreamer.kt | 32 --- .../streamers/file/AudioOnlyTsFileStreamer.kt | 36 --- .../file/BaseAudioOnlyFileStreamer.kt | 113 --------- .../streamers/file/BaseCameraFileStreamer.kt | 115 --------- .../streamers/file/CameraFlvFileStreamer.kt | 35 --- .../streamers/file/CameraMp4FileStreamer.kt | 35 --- .../streamers/file/CameraTsFileStreamer.kt | 39 --- .../CameraStreamerConfigurationInfo.kt | 14 +- .../helpers/StreamerConfigurationInfo.kt | 28 +-- .../streamers/interfaces/ICallbackStreamer.kt | 66 +++++ .../streamers/interfaces/ICameraStreamer.kt | 10 +- .../interfaces/ICoroutineStreamer.kt | 78 ++++++ .../streamers/interfaces/IFileStreamer.kt | 37 --- .../streamers/interfaces/ILiveStreamer.kt | 56 ----- .../streamers/interfaces/IStreamer.kt | 42 ++-- .../live/BaseAudioOnlyLiveStreamer.kt | 92 ------- .../streamers/live/BaseCameraLiveStreamer.kt | 95 ------- .../live/BaseScreenRecorderLiveStreamer.kt | 95 ------- .../StreamerLifeCycleObserver.kt | 17 +- .../utils/ChunkedFileOutputStream.kt | 1 - .../streampack/utils/StreamerExtensions.kt | 12 +- core/src/main/res/values/strings.xml | 2 - .../{ => composites}/FileSinkTest.kt | 70 +++--- .../flv/amf/containers/AmfEcmaArrayTest.kt | 4 +- .../flv/amf/primitives/AmfBooleanTest.kt | 4 +- .../muxers/flv/amf/primitives/AmfInt32Test.kt | 4 +- .../amf/primitives/AmfNamedParameterTest.kt | 2 +- .../flv/amf/primitives/AmfStringTest.kt | 4 +- .../muxers/flv/tags/OnMetadataTest.kt | 2 +- .../muxers/mp4/MP4ResourcesUtils.kt | 2 +- .../mp4/boxes/AVCConfigurationBoxTest.kt | 4 +- .../muxers/mp4/boxes/AVCSampleEntryTest.kt | 4 +- .../muxers/mp4/boxes/BitRateBoxTest.kt | 4 +- .../muxers/mp4/boxes/ChunkOffsetBoxTest.kt | 4 +- .../mp4/boxes/DataInformationBoxTest.kt | 4 +- .../muxers/mp4/boxes/DataReferenceBoxTest.kt | 4 +- .../muxers/mp4/boxes/FileTypeBoxTest.kt | 4 +- .../mp4/boxes/HEVCConfigurationBoxTest.kt | 4 +- .../muxers/mp4/boxes/HEVCSampleEntryTest.kt | 4 +- .../muxers/mp4/boxes/HandlerBoxTest.kt | 4 +- .../mp4/boxes/MP4AudioSampleEntryTest.kt | 4 +- .../mp4/boxes/MovieFragmentHeaderBoxTest.kt | 4 +- .../boxes/MovieFragmentRandomAccessBoxTest.kt | 4 +- .../muxers/mp4/boxes/MovieHeaderBoxTest.kt | 4 +- .../muxers/mp4/boxes/OpusSampleEntryTest.kt | 4 +- .../muxers/mp4/boxes/SampleSizeBoxTest.kt | 4 +- .../muxers/mp4/boxes/SampleToChunkBoxTest.kt | 4 +- .../mp4/boxes/SoundMediaHeaderBoxTest.kt | 4 +- .../muxers/mp4/boxes/SyncSampleBoxTest.kt | 4 +- .../muxers/mp4/boxes/TimeToSampleBoxTest.kt | 4 +- ...TrackFragmentBaseMediaDecodeTimeBoxTest.kt | 4 +- .../mp4/boxes/TrackFragmentHeaderBoxTest.kt | 8 +- .../boxes/TrackFragmentRandomAccessBoxTest.kt | 4 +- .../muxers/mp4/boxes/TrackHeaderBoxTest.kt | 4 +- .../muxers/mp4/boxes/TrackRunBoxTest.kt | 8 +- .../mp4/boxes/VideoMediaHeaderBoxTest.kt | 4 +- .../{ => composites}/muxers/ts/TSMuxerTest.kt | 123 +++++---- .../muxers/ts/TSResourcesUtils.kt | 2 +- .../ts/descriptors/AdaptationFieldTest.kt | 4 +- .../muxers/ts/packets/PesTest.kt | 6 +- .../muxers/ts/packets/TransportStreamTest.kt | 10 +- .../muxers/ts/tables/PatTest.kt | 18 +- .../muxers/ts/tables/PesHeaderTest.kt | 6 +- .../muxers/ts/tables/PmtTest.kt | 18 +- .../muxers/ts/tables/SdtTest.kt | 16 +- .../muxers/ts/tables/TableHeaderTest.kt | 4 +- .../muxers/ts/utils/MockUtils.kt | 10 +- .../{ => composites}/muxers/ts/utils/Utils.kt | 8 +- core_settings.gradle | 1 + .../streampack/app/ui/main/PreviewFragment.kt | 12 +- .../app/ui/main/PreviewViewModel.kt | 51 ++-- .../streampack/app/utils/Extensions.kt | 16 +- .../streampack/app/utils/StreamerFactory.kt | 162 ------------ .../streampack/app/utils/StreamerManager.kt | 188 ++++++++------ demos/screenrecorder/build.gradle | 1 + .../src/main/AndroidManifest.xml | 6 +- .../screenrecorder/Configuration.kt | 19 -- .../streampack/screenrecorder/MainActivity.kt | 174 +++++-------- .../DemoScreenRecorderRtmpLiveService.kt | 63 ----- ...ervice.kt => DemoScreenRecorderService.kt} | 54 +++- ...ptorTest.kt => RtmpMediaDescriptorTest.kt} | 13 +- .../endpoints/composites/RtmpEndpoint.kt} | 29 +-- .../endpoints/composites/sinks/RtmpSink.kt | 117 +++++++++ .../composites/sinks/utils/Extensions.kt | 13 + .../rtmp/internal/endpoints/sinks/RtmpSink.kt | 120 --------- .../services/ScreenRecorderRtmpLiveService.kt | 72 ------ .../rtmp/streamers/CameraRtmpLiveStreamer.kt | 52 ---- .../ScreenRecorderRtmpLiveStreamer.kt | 56 ----- ...iptorTest.kt => SrtMediaDescriptorTest.kt} | 13 +- .../endpoints/composites/SrtEndpoint.kt | 44 ++++ .../{ => composites}/sinks/SrtSink.kt | 91 ++++--- .../composites/sinks/utils/Extensions.kt | 13 + .../regulator/srt/SrtRegulatorController.kt | 80 ++++++ .../services/ScreenRecorderSrtLiveService.kt | 166 ------------- .../srt/streamers/AudioOnlySrtLiveStreamer.kt | 159 ------------ .../srt/streamers/CameraSrtLiveStreamer.kt | 231 ----------------- .../ScreenRecorderSrtLiveStreamer.kt | 235 ------------------ .../streamers/interfaces/ISrtLiveStreamer.kt | 78 ------ services/.gitignore | 1 + services/build.gradle | 19 ++ services/proguard-rules.pro | 21 ++ services/src/main/AndroidManifest.xml | 6 + .../services/DefaultScreenRecorderService.kt | 158 +++++------- .../services}/utils/NotificationUtils.kt | 2 +- services/src/main/res/values/attrs.xml | 22 ++ .../streampack/ui/views/PreviewView.kt | 6 +- 250 files changed, 2745 insertions(+), 4003 deletions(-) rename core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/{BaseAudioOnlyStreamerTest.kt => AudioOnlyStreamerTest.kt} (50%) rename core/src/androidTest/java/io/github/thibaultbee/streampack/utils/{AndroidUtils.kt => DataUtils.kt} (79%) rename core/src/{main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyMp4FileStreamer.kt => androidTest/java/io/github/thibaultbee/streampack/utils/FileUtils.kt} (55%) create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/MediaDescriptor.kt rename extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpConnectionDescriptor.kt => core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/RtmpMediaDescriptor.kt (82%) rename extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/data/SrtConnectionDescriptor.kt => core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/SrtMediaDescriptor.kt (65%) create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/UriMediaDescriptor.kt create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/DynamicEndpoint.kt create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaContainerType.kt create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaSinkType.kt create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/CompositeEndpoints.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/ConnectableCompositeEndpoint.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/FileCompositeEndpoint.kt rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/IMuxer.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/FlvMuxer.kt (86%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/FlvMuxerInfo.kt (70%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/AmfParameter.kt (72%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/containers/AmfContainer.kt (78%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/containers/AmfEcmaArray.kt (73%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/containers/AmfObject.kt (77%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfBoolean.kt (75%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfInt16.kt (81%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfInt24.kt (82%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfInt32.kt (80%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfNamedParameter.kt (84%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfNull.kt (73%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfNumber.kt (74%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfString.kt (78%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/AVTagsFactory.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/AudioTag.kt (98%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/FlvHeader.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/FlvTag.kt (96%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/OnMetadata.kt (90%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/video/ExtendedVideoTag.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/video/VideoTag.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/video/VideoTagFactory.kt (86%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/MP4Muxer.kt (80%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/MP4MuxerInfo.kt (90%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/AV1CodecConfigurationBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/AVCConfigurationBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/BitRateBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/Box.kt (95%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/ChunkOffsetBox.kt (95%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/CleanApertureBox.kt (90%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/DataEntryBox.kt (95%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/DataInformationBox.kt (90%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/DataReferenceBox.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/ESDSBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/FileTypeBox.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/HEVCConfigurationBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/HandlerBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MediaBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MediaDataBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MediaHeaderBox.kt (90%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MediaInformationBox.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieExtendsBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieFragmentBox.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieFragmentHeaderBox.kt (90%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieFragmentRandomAccessBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieFragmentRandomAccessOffsetBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieHeaderBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/NullMediaHeaderBox.kt (87%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/OpusSpecificBox.kt (95%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/PixelAspectRatioBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SampleDescriptionBox.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SampleEntry.kt (98%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SampleSizeBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SampleTableBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SampleToChunkBox.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SyncSampleBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TimeToSampleBox.kt (96%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackExtendsBox.kt (81%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackFragmentBox.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackFragmentHeaderBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackFragmentRandomAccessBox.kt (96%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackHeaderBox.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackRunBox.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TypeMediaHeaderBox.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/VPCodecConfigurationBox.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/models/Chunk.kt (96%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/models/MovieBoxFactory.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/models/SampleFlags.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/models/Segment.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/models/Segmenter.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/models/SegmenterFactory.kt (77%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/models/Track.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/models/TrackChunks.kt (82%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/utils/ConfigExtensions.kt (72%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/utils/TimeUtils.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/README.md (100%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/TSMuxer.kt (90%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/TSMuxerInfo.kt (77%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/data/ITSElement.kt (89%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/data/Service.kt (77%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/data/Stream.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{muxers/ts/data/TsServiceInfo.kt => composites/muxers/ts/data/TSServiceInfo.kt} (87%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/descriptors/AdaptationField.kt (93%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/Pat.kt (78%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/Pes.kt (79%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/PesHeader.kt (94%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/Pmt.kt (90%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/Psi.kt (86%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/Sdt.kt (85%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/TS.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/TableHeader.kt (92%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/utils/CRC32.kt (98%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/utils/MuxerConst.kt (91%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/utils/TSConst.kt (88%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/utils/TSOutputCallback.kt (71%) create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ContentSink.kt rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/sinks/FakeSink.kt (57%) create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/FileSink.kt rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/sinks/ILiveSink.kt (62%) rename core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/sinks/ISink.kt (54%) rename core/src/main/java/io/github/thibaultbee/streampack/{listeners/OnErrorListener.kt => internal/endpoints/composites/sinks/SinkConfiguration.kt} (65%) delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/FileSink.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/IFileSink.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/internal/events/EventHandler.kt rename core/src/main/java/io/github/thibaultbee/streampack/streamers/{bases/BaseAudioOnlyStreamer.kt => DefaultAudioOnlyStreamer.kt} (74%) rename core/src/main/java/io/github/thibaultbee/streampack/streamers/{bases/BaseCameraStreamer.kt => DefaultCameraStreamer.kt} (71%) rename core/src/main/java/io/github/thibaultbee/streampack/streamers/{bases/BaseScreenRecorderStreamer.kt => DefaultScreenRecorderStreamer.kt} (77%) rename core/src/main/java/io/github/thibaultbee/streampack/streamers/{bases/BaseStreamer.kt => DefaultStreamer.kt} (78%) delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyFlvFileStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyTsFileStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/file/BaseAudioOnlyFileStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/file/BaseCameraFileStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraFlvFileStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraMp4FileStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraTsFileStreamer.kt create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICallbackStreamer.kt create mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICoroutineStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/IFileStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ILiveStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseAudioOnlyLiveStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseCameraLiveStreamer.kt delete mode 100644 core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseScreenRecorderLiveStreamer.kt rename core/src/main/java/io/github/thibaultbee/streampack/streamers/{ => observers}/StreamerLifeCycleObserver.kt (69%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/FileSinkTest.kt (70%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/containers/AmfEcmaArrayTest.kt (76%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfBooleanTest.kt (75%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfInt32Test.kt (55%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfNamedParameterTest.kt (90%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/amf/primitives/AmfStringTest.kt (73%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/flv/tags/OnMetadataTest.kt (98%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/MP4ResourcesUtils.kt (92%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/AVCConfigurationBoxTest.kt (92%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/AVCSampleEntryTest.kt (93%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/BitRateBoxTest.kt (85%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/ChunkOffsetBoxTest.kt (85%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/DataInformationBoxTest.kt (85%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/DataReferenceBoxTest.kt (87%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/FileTypeBoxTest.kt (89%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/HEVCConfigurationBoxTest.kt (96%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/HEVCSampleEntryTest.kt (95%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/HandlerBoxTest.kt (85%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MP4AudioSampleEntryTest.kt (93%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieFragmentHeaderBoxTest.kt (85%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieFragmentRandomAccessBoxTest.kt (95%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/MovieHeaderBoxTest.kt (87%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/OpusSampleEntryTest.kt (88%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SampleSizeBoxTest.kt (99%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SampleToChunkBoxTest.kt (86%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SoundMediaHeaderBoxTest.kt (84%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/SyncSampleBoxTest.kt (91%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TimeToSampleBoxTest.kt (89%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBoxTest.kt (85%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackFragmentHeaderBoxTest.kt (78%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackFragmentRandomAccessBoxTest.kt (92%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackHeaderBoxTest.kt (88%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/TrackRunBoxTest.kt (87%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/mp4/boxes/VideoMediaHeaderBoxTest.kt (84%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/TSMuxerTest.kt (69%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/TSResourcesUtils.kt (92%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/descriptors/AdaptationFieldTest.kt (88%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/PesTest.kt (93%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/packets/TransportStreamTest.kt (88%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/tables/PatTest.kt (64%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/tables/PesHeaderTest.kt (84%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/tables/PmtTest.kt (67%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/tables/SdtTest.kt (64%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/tables/TableHeaderTest.kt (88%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/utils/MockUtils.kt (82%) rename core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/{ => composites}/muxers/ts/utils/Utils.kt (70%) delete mode 100644 demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/StreamerFactory.kt delete mode 100644 demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderRtmpLiveService.kt rename demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/{DemoScreenRecorderSrtLiveService.kt => DemoScreenRecorderService.kt} (50%) rename extensions/rtmp/src/androidTest/java/io/github/thibaultbee/streampack/ext/rtmp/data/{RtmpConnectionDescriptorTest.kt => RtmpMediaDescriptorTest.kt} (86%) rename extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/{streamers/AudioOnlyRtmpLiveStreamer.kt => internal/endpoints/composites/RtmpEndpoint.kt} (50%) create mode 100644 extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/sinks/RtmpSink.kt create mode 100644 extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/sinks/utils/Extensions.kt delete mode 100644 extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/sinks/RtmpSink.kt delete mode 100644 extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/services/ScreenRecorderRtmpLiveService.kt delete mode 100644 extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/CameraRtmpLiveStreamer.kt delete mode 100644 extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/ScreenRecorderRtmpLiveStreamer.kt rename extensions/srt/src/androidTest/java/io/github/thibaultbee/streampack/ext/srt/data/{SrtConnectionDescriptorTest.kt => SrtMediaDescriptorTest.kt} (84%) create mode 100644 extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/SrtEndpoint.kt rename extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/{ => composites}/sinks/SrtSink.kt (61%) create mode 100644 extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/sinks/utils/Extensions.kt create mode 100644 extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/regulator/srt/SrtRegulatorController.kt delete mode 100644 extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/services/ScreenRecorderSrtLiveService.kt delete mode 100644 extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/AudioOnlySrtLiveStreamer.kt delete mode 100644 extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/CameraSrtLiveStreamer.kt delete mode 100644 extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/ScreenRecorderSrtLiveStreamer.kt delete mode 100644 extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/interfaces/ISrtLiveStreamer.kt create mode 100644 services/.gitignore create mode 100644 services/build.gradle create mode 100644 services/proguard-rules.pro create mode 100644 services/src/main/AndroidManifest.xml rename core/src/main/java/io/github/thibaultbee/streampack/streamers/services/BaseScreenRecorderService.kt => services/src/main/java/io/github/thibaultbee/streampack/services/DefaultScreenRecorderService.kt (63%) rename {core/src/main/java/io/github/thibaultbee/streampack => services/src/main/java/io/github/thibaultbee/streampack/services}/utils/NotificationUtils.kt (98%) create mode 100644 services/src/main/res/values/attrs.xml diff --git a/DEVELOPER_README.md b/DEVELOPER_README.md index 6f65baeeb..89498ed59 100644 --- a/DEVELOPER_README.md +++ b/DEVELOPER_README.md @@ -15,39 +15,44 @@ A class that represents an audio or video encoders. Only Android MediaCodec API `Endpoint`: The last element of a live streaming pipeline. It is responsible for handling the frames after the encoder. -It could be composed of a `Muxer` and a `Sink`. +The endpoint could be a remote server (RTMP, SRT,...) or a file (FLV, MPEG-TS,...). +The main endpoint is `CompositeEndpoint` that is composed of a `Muxer` and a `Sink`. `Muxer`: -A class that packs audio and video frames to a container (FLV, MPEG-TS, MP4,...). +A process that packs audio and video frames to a container (FLV, MPEG-TS, MP4,...). +The `CompositeEndpoint` is composed of a `IMuxer`. `Sink`: -A class that sends the container to a remote server (RTMP, SRT,...) or to a file. +A process that sends the container to a remote server (RTMP, SRT,...) or to a file. +The `CompositeEndpoint` is composed of a `ISink`. `Streamer`: A class that represent a audio and/or video live streaming pipeline. It manages sources, encoders, muxers, endpoints,... and have lot of tools. They are the most important class for users. - -![streamer.png](https://github.com/ThibaultBee/StreamPack/blob/master/docs/assets/streamer.png) +Unless explicitly stated, the `Endpoint` is inferred from the `MediaDescriptor` object thanks to +the `DynamicEndpoint`. `Streamer element`: -Could be a `Source`, `Encoder`, `Muxer`, or `Endpoint`. They implement the `Streamable`. +Could be a `Source`, `Encoder`, `Muxer`, or `Endpoint`. They implement the `Streamable` and they +might have a public interface to access specific info. `Info`: A class that provides a set of methods to help to `streamer` configuration such as supported resolutions,... It comes with an instantiated `Streamer` object: ```kotlin -val info = streamer.info +val info = streamer.getInfo(MediaDescriptor(`media uri`)) ``` They might be different for each `Streamer` object. For example, a `FlvStreamer` object will not -have the same `Helper` object as a `TsStreamer` object because FLV does not support a wide range of +have the same `Info` object as a `TsStreamer` object because FLV does not support a wide range of codecs, audio sample rate,... `Settings`: -Each streamer elements have a public interface `Settings` that allows go have access to specific -information or configurations: - +Each streamer elements have a public interface that allows go have access to specific +information or configuration. +For example, the `VideoEncoder` object has a `bitrate` property that allows to get and set the +current video bitrate. Example: ```kotlin @@ -57,25 +62,20 @@ val bitrate = streamer.videoEncoder!!.bitrate streamer.videoEncoder!!.bitrate = 2000000 ``` -`Extensions`: -A library that adds new features from native libraries. It often comes with a `Streamer elements` -and specific pipelines. - ## Streamers -The base streamer class is `BaseStreamer`. All other streamers inherit from it. Then 2 specifics +The streamer implementation is the `DefaultStreamer`. All other streamers inherit from it. Then 2 +specifics base streamers inherit from it: -- `BaseCameraStreamer`: A streamer that streams from a camera and microphone. It adds `startPreview` +- `DefaultCameraStreamer`: A streamer that streams from a camera and microphone. It + adds `startPreview` , `stopPreview` methods to the `Streamer` object as well as a camera settings. -- `BaseScreenRecorderStreamer`: A streamer that streams from the phone screen and microphone. It +- `DefaultScreenRecorderStreamer`: A streamer that streams from the phone screen and microphone. It adds specific methods for screen recorder as a API to set activity result. -Then these base streamers are specialized for a File or for a Live: - -- `BaseFileStreamer`: A streamer that streams to a file. That means you will find - `BaseFileStreamer` for MPEG-TS and one for FLV. -- `BaseLiveStreamer`: A streamer that streams to a remote server (RTMP or SRT both in `extensions`). +To endpoint of a `Streamer` is inferred from the `MediaDescriptor` object passed to the `Streamer` +by `open` or `startStream` methods. ## Sources @@ -87,6 +87,21 @@ There are 2 types of sources: a `Surface`. Its purpose is to improve encoder performance. For example, it suits camera and screen recorder. `Surface` sources implement `ISurfaceSource`. +@startuml +interface IVideoSource { + ++ hasSurface: Boolean ++ encoderSurface: Surface? ++ getFrame(): ByteBuffer + } + +interface IAudioSource { + ++ getFrame(): ByteBuffer + } + @enduml ++ + To create a new audio source, implements a `IAudioSource`. It inherits from `IFrameSource`. To create a new video source, implements a `IVideSource`. It inherits from both `IFrameCapture` @@ -106,13 +121,69 @@ If your video source is a `ByteBuffer` source, set: ## Encoders -Both `AudioMediaCodecEncoder` and `VideoMediaCodecEncoder` inherit from `MediaCodecEncoder`. They -are using Android `MediaCodec` API in asynchronous mode. - -## Muxers +The only encoder is based on Android `MediaCodec` API. It implements the `IEncoder` interface. -They implement the `IMuxer` interface. +@startuml +interface IEncoder { +} +@enduml ## Endpoints -They implement the `IEndpoint` interface. Use specific `ILiveEndpoint` for live streaming. \ No newline at end of file +They implement the `IEndpoint` interface. + +@startuml +interface IEndpoint { + ++ open() ++ close() ++ write() + } + +class CompositeEndpoint { + ++ muxer: IMuxer ++ sink: ISink + } + @enduml + +### Muxers + +They implement the `IMuxer` interface. + +### Sinks + +They implement the `ISink` interface. + +### Streamers + +The implement the `ICoroutineStreamer` interface. + +@startuml +class DefaultStreamer { + ++ videoSource: IVideoSource ++ audioSource: IAudioSource ++ endoint: IEndpoint + +- videoEncoder: IEncoder +- audioEncoder: IEncoder + } + @enduml + +@startuml +rectangle DefaultCameraStreamer { +[CameraSource] as VideoSource +[MicrophoneSource] as AudioSource +[Encoder] as VideoEncoder +[Encoder] as AudioEncoder +[Endpoint] as Endpoint +VideoSource -r-> VideoEncoder +AudioSource -r-> AudioEncoder +VideoEncoder -r-> Endpoint +AudioEncoder -r-> Endpoint +AudioSource -d[hidden]-> VideoSource +AudioEncoder -d[hidden]-> VideoEncoder +} +} +@enduml \ No newline at end of file diff --git a/README.md b/README.md index 017ebb53e..e8be62595 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ dependencies { implementation 'io.github.thibaultbee:streampack:2.6.0' // For UI (incl. PreviewView) implementation 'io.github.thibaultbee:streampack-ui:2.6.0' + // For ScreenRecorder service + implementation 'io.github.thibaultbee:streampack-services:2.6.0' // For RTMP implementation 'io.github.thibaultbee:streampack-extension-rtmp:2.6.0' // For SRT @@ -108,10 +110,9 @@ If you want to create a new application, you should use the template [StreamPack boilerplate](https://github.com/ThibaultBee/StreamPack-boilerplate). In 5 minutes, you will be able to stream live video to your server. -1. Add [permissions](#permissions) to your `AndroidManifest.xml` and request them in your - Activity/Fragment. +1. Request the required permissions in your Activity/Fragment. -2. Create a `SurfaceView` to display camera preview in your layout +2. Creates a `SurfaceView` to display camera preview in your layout As a camera preview, you can use a `SurfaceView`, a `TextureView` or any `View` where that can provide a `Surface`. @@ -129,13 +130,13 @@ To simplify integration, StreamPack provides an `PreviewView`. `app:enableZoomOnPinch` is a boolean to enable zoom on pinch gesture. -3. Instantiate the streamer (main live streaming class) +3. Instantiates the streamer (main live streaming class) ```kotlin -val streamer = CameraSrtLiveStreamer(context = requireContext()) +val streamer = DefaultCameraStreamer(context = requireContext()) ``` -4. Configure audio and video settings +4. Configures audio and video settings ```kotlin val audioConfig = AudioConfig( @@ -153,7 +154,7 @@ val videoConfig = VideoConfig( streamer.configure(audioConfig, videoConfig) ``` -5. Inflate the camera preview with the streamer +5. Inflates the camera preview with the streamer ```kotlin /** @@ -166,17 +167,25 @@ preview.streamer = streamer streamer.startPreview(preview) ``` -6. Start the live streaming +6. Starts the live streaming ```kotlin -streamer.startStream(ip, port) +val descriptor = + UriMediaDescriptor("rtmps://serverip:1935/s/streamKey") // For RTMP/RTMPS. Uri also supports SRT url, file, content path,... +/** + * Alternatively, you can use object syntax: + * - RtmpConnectionDescriptor("rtmps", "serverip", 1935, "s", "streamKey") // For RTMP/RTMPS + * - SrtConnectionDescriptor("serverip", 1234) // For SRT + */ + +streamer.startStream() ``` -7. Stop and release the streamer +7. Stops and releases the streamer ```kotlin streamer.stopStream() -streamer.disconnect() +streamer.close() // Disconnect from server or close the file streamer.stopPreview() // The StreamerSurfaceView will be automatically stop the preview streamer.release() ``` @@ -242,7 +251,7 @@ You will also have to declare the `Service`, ```xml - + @@ -267,30 +276,34 @@ It is easy: if your server has SRT support, use SRT otherwise use RTMP. ### Streamers -Let's start with some definitions! `Streamers` are classes that represent a live streaming pipeline: -capture, encode, mux and send. They comes in multiple flavours: with different audio and video -source, with different endpoints and functionalities... 3 types of base streamers are available: - -- `CameraStreamers`: for streaming from camera -- `ScreenRecorderStreamers`: for streaming from screen -- `AudioOnlyStreamers`: for streaming audio only - -You can find specific streamers for File or for Live. Currently, there are 2 main endpoints: +Let's start with some definitions! `Streamers` are classes that represent a streaming pipeline: +capture, encode, mux and send. +They comes in multiple flavours: with different audio and video source. 3 types of base streamers +are available: -- `FileStreamer`: for streaming to file -- `LiveStreamer`: for streaming to a RTMP or a SRT live streaming server +- `DefaultCameraStreamer`: for streaming from camera +- `DefaultScreenRecorderStreamer`: for streaming from screen +- `DefaultAudioOnlyStreamer`: for streaming audio only -For example, you can use `AudioOnlyFlvFileStreamer` to stream from microphone only to a FLV file. -Another example, you can use `CameraRtmpLiveStreamer` to stream from camera to a RTMP server. +Since 3.0.0, the endpoint of a `Streamer` is inferred from the `MediaDescriptor` object passed to +the `open` or `startStream` methods. It is possible to limit the possibility of the endpoint by +implementing your own `DynamicEndpoint.Factory` or passing a endpoint as the `Streamer` `endpoint` +parameter. -If a streamer is missing, of course, you can also create your own. You should definitely submit it -in a [pull request](https://github.com/ThibaultBee/StreamPack/pulls). +To create a `Streamer` for a new source, you have to create a new `Streamer` class that inherits +from `DefaultStreamer`. ### Get device capabilities Have you ever wonder: "What are the supported resolution of my cameras?" or "What is the supported sample rate of my audio codecs?"? `Info` classes are made for this. All `Streamer` comes with a -specific `Info` object (I am starting to have the feeling I repeat myself): +specific `Info` object: + +```kotlin +val info = streamer.getInfo(MediaDescriptor("rtmps://serverip:1935/s/streamKey")) +``` + +For static endpoint or an opened dynamic endpoint, you can directly get the info: ```kotlin val info = streamer.info @@ -299,32 +312,34 @@ val info = streamer.info ### Get extended settings If you are looking for more settings on streamer, like the exposure compensation of your camera, you -must have a look on `Settings` class. All together: "All `Streamer` comes with a specific `Settings` -object": +must have a look on `Settings` class. Each `Streamer` elements (such +as `VideoSource`, `AudioSource`,...) +comes with a public interface that allows to have access to specific information or configuration. ```kotlin -streamer.settings + (streamer.videoSource as IPublicCameraSource).settings ``` For example, if you want to change the exposure compensation of your camera, on a `CameraStreamers` you can do it like this: ```kotlin -streamer.settings.camera.exposure.compensation = value + (streamer.videoSource as IPublicCameraSource).settings.exposure.compensation = value ``` Moreover you can check exposure range and step with: ```kotlin -streamer.settings.camera.exposure.availableCompensationRange -streamer.settings.camera.exposure.availableCompensationStep + (streamer.videoSource as IPublicCameraSource).settings.exposure.availableCompensationRange +(streamer.videoSource as IPublicCameraSource).settings.exposure.availableCompensationStep ``` ### Screen recorder Service -To record the screen, you have to use one of the `ScreenRecorderStreamers` inside +To record the screen, you have to use the `DefaultScreenRecorderStreamer` inside an [Android Service](https://developer.android.com/guide/components/services). To simplify this -integration, StreamPack provides several `ScreenRecorderService` classes. Extends one of these class +integration, StreamPack provides the `DefaultScreenRecorderService` classes. Extends one of these +class and overrides `onNotification` to customise the notification. ### Android SDK version diff --git a/core/build.gradle b/core/build.gradle index 0fbb34bed..9289cfdd6 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -18,8 +18,11 @@ dependencies { testImplementation 'androidx.test:rules:1.5.0' testImplementation 'junit:junit:4.13.2' testImplementation 'io.mockk:mockk:1.12.2' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1' + testImplementation "org.robolectric:robolectric:4.12.2" androidTestImplementation 'androidx.test:rules:1.5.0' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1' } diff --git a/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/BaseAudioOnlyStreamerTest.kt b/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/AudioOnlyStreamerTest.kt similarity index 50% rename from core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/BaseAudioOnlyStreamerTest.kt rename to core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/AudioOnlyStreamerTest.kt index ede63e4e7..c75b3a260 100644 --- a/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/BaseAudioOnlyStreamerTest.kt +++ b/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/AudioOnlyStreamerTest.kt @@ -15,30 +15,23 @@ */ package io.github.thibaultbee.streampack.streamer -import io.github.thibaultbee.streampack.internal.endpoints.composites.CompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.FlvMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSMuxer -import io.github.thibaultbee.streampack.internal.endpoints.sinks.FakeSink +import androidx.core.net.toUri +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor import io.github.thibaultbee.streampack.streamer.testcases.AudioOnlyStreamerTestCase -import io.github.thibaultbee.streampack.streamers.bases.BaseAudioOnlyStreamer -import io.github.thibaultbee.streampack.utils.AndroidUtils +import io.github.thibaultbee.streampack.utils.FileUtils class TsAudioOnlyStreamerTest : AudioOnlyStreamerTestCase() { - override val streamer = BaseAudioOnlyStreamer( - context, - CompositeEndpoint( - TSMuxer().apply { addService(AndroidUtils.fakeServiceInfo()) }, - FakeSink() - ) - ) + override val descriptor: MediaDescriptor = + UriMediaDescriptor(FileUtils.createCacheFile("audio.ts").toUri()) } class FlvAudioOnlyStreamerTest : AudioOnlyStreamerTestCase() { - override val streamer = BaseAudioOnlyStreamer( - context, - CompositeEndpoint( - FlvMuxer(writeToFile = false), - FakeSink() - ), - ) + override val descriptor: MediaDescriptor = + UriMediaDescriptor(FileUtils.createCacheFile("audio.flv").toUri()) +} + +class Mp4AudioOnlyStreamerTest : AudioOnlyStreamerTestCase() { + override val descriptor: MediaDescriptor = + UriMediaDescriptor(FileUtils.createCacheFile("audio.mp4").toUri()) } \ No newline at end of file diff --git a/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/AudioOnlyStreamerTestCase.kt b/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/AudioOnlyStreamerTestCase.kt index 20e720b8b..8732144b5 100644 --- a/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/AudioOnlyStreamerTestCase.kt +++ b/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/AudioOnlyStreamerTestCase.kt @@ -16,33 +16,36 @@ package io.github.thibaultbee.streampack.streamer.testcases import android.Manifest +import android.content.Context import android.util.Log +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule -import io.github.thibaultbee.streampack.streamers.bases.BaseAudioOnlyStreamer -import io.github.thibaultbee.streampack.utils.AndroidUtils -import kotlinx.coroutines.runBlocking +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.streamers.DefaultAudioOnlyStreamer +import io.github.thibaultbee.streampack.utils.DataUtils +import kotlinx.coroutines.test.runTest import org.junit.Assert.fail import org.junit.Rule import org.junit.Test -abstract class AudioOnlyStreamerTestCase : - StreamerTestCase() { - abstract override val streamer: BaseAudioOnlyStreamer +abstract class AudioOnlyStreamerTestCase { + private val context: Context = InstrumentationRegistry.getInstrumentation().context + private val streamer = DefaultAudioOnlyStreamer(context) + + protected abstract val descriptor: MediaDescriptor @get:Rule val runtimePermissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.RECORD_AUDIO) @Test - override fun defaultUsageTest() { + fun defaultUsageTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream(descriptor) + streamer.stopStream() streamer.release() } catch (e: Exception) { Log.e(TAG, "defaultUsageTest: exception: ", e) @@ -50,29 +53,12 @@ abstract class AudioOnlyStreamerTestCase : } } - @Test - override fun defaultUsageTest2() { - try { - streamer.configure( - AndroidUtils.fakeValidAudioConfig() - ) - runBlocking { - streamer.startStream() - streamer.stopStream() - } - streamer.release() - } catch (e: Exception) { - Log.e(TAG, "defaultUsageTest2: exception: ", e) - fail("Default usage must not throw exception $e") - } - } - // Single method calls @Test - override fun configureAudioTest() { + fun configureAudioOnlyTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) } catch (e: Exception) { Log.e(TAG, "configureAudioTest: exception: ", e) @@ -81,10 +67,10 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun configureVideoTest() { + fun configureVideoOnlyTest() { try { streamer.configure( - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidVideoConfig() ) fail("Must not be possible to configure video") } catch (_: Exception) { @@ -92,11 +78,11 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun configureTest() { + fun configureTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) fail("Must not be possible to configure video") } catch (_: Exception) { @@ -104,10 +90,10 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun configureErrorTest() { + fun configureErrorTest() { try { streamer.configure( - AndroidUtils.fakeInvalidAudioConfig() + DataUtils.dummyInvalidAudioConfig() ) fail("Invalid configuration must throw an exception") } catch (_: Exception) { @@ -116,14 +102,12 @@ abstract class AudioOnlyStreamerTestCase : // Multiple methods calls @Test - override fun configureStartStreamTest() { + fun configureStartStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) - runBlocking { - streamer.startStream() - } + streamer.startStream(descriptor) } catch (e: Exception) { Log.e(TAG, "configureStartStreamTest: exception: ", e) fail("Must be possible to configure/startStream but catches exception: $e") @@ -131,10 +115,10 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun configureReleaseTest() { + fun configureReleaseTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) streamer.release() } catch (e: Exception) { @@ -144,14 +128,12 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun configureStopStreamTest() { + fun configureStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) - runBlocking { - streamer.stopStream() - } + streamer.stopStream() } catch (e: Exception) { Log.e(TAG, "configureStopStreamTest: exception: ", e) fail("Must be possible to configure/stopStream but catches exception: $e") @@ -159,14 +141,12 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun startStreamReleaseTest() { + fun startStreamReleaseTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) - runBlocking { - streamer.startStream() - } + streamer.startStream(descriptor) streamer.release() } catch (e: Exception) { Log.e(TAG, "startStreamReleaseTest: exception: ", e) @@ -175,15 +155,13 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun startStreamStopStreamTest() { + fun startStreamStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream(descriptor) + streamer.stopStream() } catch (e: Exception) { Log.e(TAG, "startStreamStopStreamTest: exception: ", e) fail("Must be possible to startStream/stopStream but catches exception: $e") @@ -191,16 +169,15 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun multipleStartStreamStopStreamTest() { + fun multipleStartStreamStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) (0..10).forEach { _ -> - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream(descriptor) + streamer.stopStream() + streamer.close() } } catch (e: Exception) { Log.e(TAG, "multipleStartStreamStopStreamTest: exception: ", e) @@ -209,11 +186,11 @@ abstract class AudioOnlyStreamerTestCase : } @Test - override fun multipleConfigureTest() { + fun multipleConfigureTest() { try { (0..10).forEach { _ -> streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) } } catch (e: Exception) { diff --git a/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/CameraStreamerTestCase.kt b/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/CameraStreamerTestCase.kt index 6420cf782..db1ec3097 100644 --- a/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/CameraStreamerTestCase.kt +++ b/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/CameraStreamerTestCase.kt @@ -16,13 +16,15 @@ package io.github.thibaultbee.streampack.streamer.testcases import android.Manifest +import android.content.Context import android.graphics.SurfaceTexture import android.util.Log import android.view.Surface +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule -import io.github.thibaultbee.streampack.streamers.bases.BaseCameraStreamer -import io.github.thibaultbee.streampack.utils.AndroidUtils -import kotlinx.coroutines.runBlocking +import io.github.thibaultbee.streampack.streamers.DefaultCameraStreamer +import io.github.thibaultbee.streampack.utils.DataUtils +import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Assert.fail import org.junit.Before @@ -31,7 +33,9 @@ import org.junit.Test abstract class CameraStreamerTestCase : StreamerTestCase() { - abstract override val streamer: BaseCameraStreamer + private val context: Context = InstrumentationRegistry.getInstrumentation().context + + override val streamer = DefaultCameraStreamer(context) private lateinit var surface: Surface @Before @@ -49,17 +53,15 @@ abstract class CameraStreamerTestCase : GrantPermissionRule.grant(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO) @Test - override fun defaultUsageTest() { + override fun defaultUsageTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.startPreview(surface) - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream(descriptor) + streamer.stopStream() streamer.stopPreview() streamer.release() } catch (e: Exception) { @@ -68,27 +70,6 @@ abstract class CameraStreamerTestCase : } } - @Test - override fun defaultUsageTest2() { - try { - streamer.configure( - AndroidUtils.fakeValidAudioConfig() - ) - streamer.configure( - AndroidUtils.fakeValidVideoConfig() - ) - streamer.startPreview(surface) - runBlocking { - streamer.startStream() - streamer.stopStream() - } - streamer.release() - } catch (e: Exception) { - Log.e(TAG, "defaultUsageTest2: exception: ", e) - fail("Default usage must not throw exception $e") - } - } - // Single method calls @Test fun startPreviewTest() { @@ -113,8 +94,8 @@ abstract class CameraStreamerTestCase : fun configureStopPreviewTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.stopPreview() } catch (e: Exception) { @@ -127,8 +108,8 @@ abstract class CameraStreamerTestCase : fun startPreviewReleaseTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.startPreview(surface) streamer.release() @@ -142,8 +123,8 @@ abstract class CameraStreamerTestCase : fun startPreviewStopPreviewTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.startPreview(surface) streamer.stopPreview() @@ -154,16 +135,14 @@ abstract class CameraStreamerTestCase : } @Test - fun startPreviewStopStreamTest() { + fun startPreviewStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.startPreview(surface) - runBlocking { - streamer.stopStream() - } + streamer.stopStream() } catch (e: Exception) { Log.e(TAG, "startPreviewStopStreamTest: exception: ", e) fail("Must be possible to startPreview/stopStream but catches exception: $e") @@ -172,16 +151,14 @@ abstract class CameraStreamerTestCase : @Test - override fun startStreamReleaseTest() { + override fun startStreamReleaseTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.startPreview(surface) - runBlocking { - streamer.startStream() - } + streamer.startStream(descriptor) streamer.release() } catch (e: Exception) { Log.e(TAG, "startStreamReleaseTest: exception: ", e) @@ -191,16 +168,14 @@ abstract class CameraStreamerTestCase : @Test - fun startStreamStopPreviewTest() { + fun startStreamStopPreviewTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.startPreview(surface) - runBlocking { - streamer.startStream() - } + streamer.startStream(descriptor) streamer.stopPreview() } catch (e: Exception) { Log.e(TAG, "startStreamStopPreviewTest: exception: ", e) @@ -209,17 +184,15 @@ abstract class CameraStreamerTestCase : } @Test - override fun startStreamStopStreamTest() { + override fun startStreamStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.startPreview(surface) - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream(descriptor) + streamer.stopStream() } catch (e: Exception) { Log.e(TAG, "startStreamStopStreamTest: exception: ", e) fail("Must be possible to startStream/stopStream but catches exception: $e") @@ -230,8 +203,8 @@ abstract class CameraStreamerTestCase : fun multipleStartPreviewStopPreviewTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) (0..10).forEach { _ -> streamer.startPreview(surface) @@ -244,18 +217,16 @@ abstract class CameraStreamerTestCase : } @Test - override fun multipleStartStreamStopStreamTest() { + override fun multipleStartStreamStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.startPreview(surface) (0..10).forEach { _ -> - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream(descriptor) + streamer.stopStream() } } catch (e: Exception) { Log.e(TAG, "multipleStartStreamStopStreamTest: exception: ", e) diff --git a/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/StreamerTestCase.kt b/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/StreamerTestCase.kt index d976b0d54..993874ba9 100644 --- a/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/StreamerTestCase.kt +++ b/core/src/androidTest/java/io/github/thibaultbee/streampack/streamer/testcases/StreamerTestCase.kt @@ -15,20 +15,18 @@ */ package io.github.thibaultbee.streampack.streamer.testcases -import android.content.Context import android.util.Log -import androidx.test.platform.app.InstrumentationRegistry -import io.github.thibaultbee.streampack.streamers.bases.BaseStreamer -import io.github.thibaultbee.streampack.utils.AndroidUtils -import kotlinx.coroutines.runBlocking +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.streamers.DefaultStreamer +import io.github.thibaultbee.streampack.utils.DataUtils +import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Assert.fail import org.junit.Test abstract class StreamerTestCase { - protected val context: Context = InstrumentationRegistry.getInstrumentation().context - - abstract val streamer: BaseStreamer + protected abstract val streamer: DefaultStreamer + protected abstract val descriptor: MediaDescriptor @After open fun tearDown() { @@ -36,16 +34,14 @@ abstract class StreamerTestCase { } @Test - open fun defaultUsageTest() { + open fun defaultUsageTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream(descriptor) + streamer.stopStream() streamer.release() } catch (e: Exception) { Log.e(TAG, "defaultUsageTest: exception: ", e) @@ -53,32 +49,12 @@ abstract class StreamerTestCase { } } - @Test - open fun defaultUsageTest2() { - try { - streamer.configure( - AndroidUtils.fakeValidAudioConfig() - ) - streamer.configure( - AndroidUtils.fakeValidVideoConfig() - ) - runBlocking { - streamer.startStream() - streamer.stopStream() - } - streamer.release() - } catch (e: Exception) { - Log.e(TAG, "defaultUsageTest2: exception: ", e) - fail("Default usage must not throw exception $e") - } - } - // Single method calls @Test - open fun configureAudioTest() { + open fun configureAudioOnlyTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig() + DataUtils.dummyValidAudioConfig() ) } catch (e: Exception) { Log.e(TAG, "configureAudioTest: exception: ", e) @@ -87,10 +63,10 @@ abstract class StreamerTestCase { } @Test - open fun configureVideoTest() { + open fun configureVideoOnlyTest() { try { streamer.configure( - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidVideoConfig() ) } catch (e: Exception) { Log.e(TAG, "configureVideoTest: exception: ", e) @@ -102,8 +78,8 @@ abstract class StreamerTestCase { open fun configureTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) } catch (e: Exception) { Log.e(TAG, "configureTest: exception: ", e) @@ -115,8 +91,8 @@ abstract class StreamerTestCase { open fun configureErrorTest() { try { streamer.configure( - AndroidUtils.fakeInvalidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyInvalidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) fail("Invalid configuration must throw an exception") } catch (_: Exception) { @@ -124,22 +100,18 @@ abstract class StreamerTestCase { } @Test - fun startStreamTest() { + fun startStreamTest() = runTest { try { - runBlocking { - streamer.startStream() - } + streamer.startStream() fail("startStream without configuration must throw an exception") } catch (_: Exception) { } } @Test - fun stopStreamTest() { + fun stopStreamTest() = runTest { try { - runBlocking { - streamer.stopStream() - } + streamer.stopStream() } catch (e: Exception) { Log.e(TAG, "stopStreamTest: exception: ", e) fail("Must be possible to only stopStream without exception: $e") @@ -158,15 +130,13 @@ abstract class StreamerTestCase { // Multiple methods calls @Test - open fun configureStartStreamTest() { + open fun configureStartStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) - runBlocking { - streamer.startStream() - } + streamer.startStream() fail("startStream without startPreview must failed") } catch (_: Exception) { } @@ -176,8 +146,8 @@ abstract class StreamerTestCase { open fun configureReleaseTest() { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) streamer.release() } catch (e: Exception) { @@ -187,15 +157,13 @@ abstract class StreamerTestCase { } @Test - open fun configureStopStreamTest() { + open fun configureStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) - runBlocking { - streamer.stopStream() - } + streamer.stopStream() } catch (e: Exception) { Log.e(TAG, "configureStopStreamTest: exception: ", e) fail("Must be possible to configure/stopStream but catches exception: $e") @@ -203,15 +171,13 @@ abstract class StreamerTestCase { } @Test - open fun startStreamReleaseTest() { + open fun startStreamReleaseTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) - runBlocking { - streamer.startStream() - } + streamer.startStream() streamer.release() } catch (e: Exception) { Log.e(TAG, "startStreamReleaseTest: exception: ", e) @@ -220,16 +186,14 @@ abstract class StreamerTestCase { } @Test - open fun startStreamStopStreamTest() { + open fun startStreamStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream() + streamer.stopStream() } catch (e: Exception) { Log.e(TAG, "startStreamStopStreamTest: exception: ", e) fail("Must be possible to startStream/stopStream but catches exception: $e") @@ -242,8 +206,8 @@ abstract class StreamerTestCase { try { (0..10).forEach { _ -> streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) } } catch (e: Exception) { @@ -253,17 +217,15 @@ abstract class StreamerTestCase { } @Test - open fun multipleStartStreamStopStreamTest() { + open fun multipleStartStreamStopStreamTest() = runTest { try { streamer.configure( - AndroidUtils.fakeValidAudioConfig(), - AndroidUtils.fakeValidVideoConfig() + DataUtils.dummyValidAudioConfig(), + DataUtils.dummyValidVideoConfig() ) (0..10).forEach { _ -> - runBlocking { - streamer.startStream() - streamer.stopStream() - } + streamer.startStream() + streamer.stopStream() } } catch (e: Exception) { Log.e(TAG, "multipleStartStreamStopStreamTest: exception: ", e) diff --git a/core/src/androidTest/java/io/github/thibaultbee/streampack/utils/AndroidUtils.kt b/core/src/androidTest/java/io/github/thibaultbee/streampack/utils/DataUtils.kt similarity index 79% rename from core/src/androidTest/java/io/github/thibaultbee/streampack/utils/AndroidUtils.kt rename to core/src/androidTest/java/io/github/thibaultbee/streampack/utils/DataUtils.kt index 9950d38e8..bae077afc 100644 --- a/core/src/androidTest/java/io/github/thibaultbee/streampack/utils/AndroidUtils.kt +++ b/core/src/androidTest/java/io/github/thibaultbee/streampack/utils/DataUtils.kt @@ -19,17 +19,17 @@ import android.media.MediaFormat import android.util.Size import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.VideoConfig -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo import kotlin.random.Random -object AndroidUtils { +object DataUtils { /** * Generates a TS service information for test * - * @return a [TsServiceInfo] for test + * @return a [TSServiceInfo] for test */ - fun fakeServiceInfo() = TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, + fun dummyServiceInfo() = TSServiceInfo( + TSServiceInfo.ServiceType.DIGITAL_TV, Random.nextInt().toShort(), "testName", "testServiceName" @@ -40,14 +40,14 @@ object AndroidUtils { * * @return a [AudioConfig] for test */ - fun fakeValidAudioConfig() = AudioConfig() + fun dummyValidAudioConfig() = AudioConfig() /** * Generates an invalid audio configuration for test * * @return a [AudioConfig] for test */ - fun fakeInvalidAudioConfig() = AudioConfig( + fun dummyInvalidAudioConfig() = AudioConfig( mimeType = MediaFormat.MIMETYPE_VIDEO_AVC // Video instead of audio ) @@ -56,7 +56,7 @@ object AndroidUtils { * * @return a [VideoConfig] for test */ - fun fakeValidVideoConfig() = VideoConfig( + fun dummyValidVideoConfig() = VideoConfig( resolution = Size(640, 360) ) @@ -66,7 +66,7 @@ object AndroidUtils { * * @return a [VideoConfig] for test */ - fun fakeInvalidVideoConfig() = VideoConfig( + fun dummyInvalidVideoConfig() = VideoConfig( mimeType = MediaFormat.MIMETYPE_AUDIO_AAC // Audio instead of video ) } \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyMp4FileStreamer.kt b/core/src/androidTest/java/io/github/thibaultbee/streampack/utils/FileUtils.kt similarity index 55% rename from core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyMp4FileStreamer.kt rename to core/src/androidTest/java/io/github/thibaultbee/streampack/utils/FileUtils.kt index 8a2031faf..230c8ac60 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyMp4FileStreamer.kt +++ b/core/src/androidTest/java/io/github/thibaultbee/streampack/utils/FileUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Thibault B. + * Copyright (C) 2024 Thibault B. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.streamers.file +package io.github.thibaultbee.streampack.utils -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4Muxer +import androidx.test.platform.app.InstrumentationRegistry import java.io.File -/** - * A [BaseAudioOnlyFileStreamer] that sends only microphone frames to a MP4 [File]. - * - * @param context application context - */ -class AudioOnlyMp4FileStreamer( - context: Context -) : BaseAudioOnlyFileStreamer( - context = context, - muxer = MP4Muxer() -) \ No newline at end of file +object FileUtils { + fun createCacheFile(name: String): File { + return File(InstrumentationRegistry.getInstrumentation().context.cacheDir, name) + } +} \ No newline at end of file diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 41c1b2796..8310db1b1 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -6,7 +6,4 @@ - - - diff --git a/core/src/main/java/io/github/thibaultbee/streampack/data/AudioConfig.kt b/core/src/main/java/io/github/thibaultbee/streampack/data/AudioConfig.kt index a7f242a24..4b9f56bb2 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/data/AudioConfig.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/data/AudioConfig.kt @@ -20,14 +20,14 @@ import android.media.MediaCodecInfo import android.media.MediaFormat import android.os.Build import io.github.thibaultbee.streampack.internal.utils.extensions.isAudio -import io.github.thibaultbee.streampack.streamers.bases.BaseStreamer +import io.github.thibaultbee.streampack.streamers.DefaultStreamer import java.security.InvalidParameterException /** * Audio configuration class. * If you don't know how to set class members, [Video encoding recommendations](https://developer.android.com/guide/topics/media/media-formats#video-encoding) should give you hints. * - * @see [BaseStreamer.configure] + * @see [DefaultStreamer.configure] */ class AudioConfig( /** diff --git a/core/src/main/java/io/github/thibaultbee/streampack/data/Config.kt b/core/src/main/java/io/github/thibaultbee/streampack/data/Config.kt index d8be4339d..1441e3e05 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/data/Config.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/data/Config.kt @@ -17,13 +17,13 @@ package io.github.thibaultbee.streampack.data import android.media.MediaFormat import io.github.thibaultbee.streampack.internal.encoders.mediacodec.MediaCodecHelper -import io.github.thibaultbee.streampack.streamers.bases.BaseStreamer +import io.github.thibaultbee.streampack.streamers.DefaultStreamer /** * Base configuration class. * If you don't know how to set class members, [Video encoding recommendations](https://developer.android.com/guide/topics/media/media-formats#video-encoding) should give you hints. * - * @see [BaseStreamer.configure] + * @see [DefaultStreamer.configure] */ open class Config( /** diff --git a/core/src/main/java/io/github/thibaultbee/streampack/data/VideoConfig.kt b/core/src/main/java/io/github/thibaultbee/streampack/data/VideoConfig.kt index d018e1329..de508fd3e 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/data/VideoConfig.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/data/VideoConfig.kt @@ -37,7 +37,7 @@ import io.github.thibaultbee.streampack.internal.utils.extensions.isDevicePortra import io.github.thibaultbee.streampack.internal.utils.extensions.isVideo import io.github.thibaultbee.streampack.internal.utils.extensions.landscapize import io.github.thibaultbee.streampack.internal.utils.extensions.portraitize -import io.github.thibaultbee.streampack.streamers.bases.BaseStreamer +import io.github.thibaultbee.streampack.streamers.DefaultStreamer import java.security.InvalidParameterException import kotlin.math.roundToInt @@ -45,7 +45,7 @@ import kotlin.math.roundToInt * Video configuration class. * If you don't know how to set class members, [Video encoding recommendations](https://developer.android.com/guide/topics/media/media-formats#video-encoding) should give you hints. * - * @see [BaseStreamer.configure] + * @see [DefaultStreamer.configure] */ class VideoConfig( /** diff --git a/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/MediaDescriptor.kt b/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/MediaDescriptor.kt new file mode 100644 index 000000000..8ca820e8c --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/MediaDescriptor.kt @@ -0,0 +1,8 @@ +package io.github.thibaultbee.streampack.data.mediadescriptor + +sealed class MediaDescriptor(val customData: List = emptyList()) { + @Suppress("UNCHECKED_CAST") + fun getCustomData(clazz: Class): T? { + return customData.firstOrNull { clazz.isInstance(it) } as T? + } +} diff --git a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpConnectionDescriptor.kt b/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/RtmpMediaDescriptor.kt similarity index 82% rename from extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpConnectionDescriptor.kt rename to core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/RtmpMediaDescriptor.kt index a0c877635..a94e069f6 100644 --- a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpConnectionDescriptor.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/RtmpMediaDescriptor.kt @@ -13,11 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.ext.rtmp.data +package io.github.thibaultbee.streampack.data.mediadescriptor import android.net.Uri import java.security.InvalidParameterException +/** + * Creates a RTMP connection descriptor from an [Uri] + */ +fun RtmpMediaDescriptor(uri: Uri) = RtmpMediaDescriptor.fromUri(uri) + /** * RTMP connection parameters * @@ -27,9 +32,9 @@ import java.security.InvalidParameterException * @param app the application name * @param streamKey the stream key */ -data class RtmpConnectionDescriptor( +class RtmpMediaDescriptor( val scheme: String, val host: String, val port: Int, val app: String, val streamKey: String -) { +) : MediaDescriptor() { val uri = Uri.Builder() .scheme(scheme) .encodedAuthority("$host:$port") @@ -37,8 +42,6 @@ data class RtmpConnectionDescriptor( .appendEncodedPath(streamKey) .build() - val url = uri.toString() - init { require(scheme == RTMP_SCHEME || scheme == RTMPS_SCHEME || scheme == RTMPT_SCHEME || scheme == RTMPE_SCHEME || scheme == RTMFP_SCHEME || scheme == RTMPTE_SCHEME || scheme == RTMPTS_SCHEME) { "Invalid scheme $scheme" } require(host.isNotBlank()) { "Invalid host $host" } @@ -62,14 +65,21 @@ data class RtmpConnectionDescriptor( private const val HTTP_DEFAULT_PORT = 80 /** - * Creates a RTMP connection from an URL + * Creates a RTMP connection descriptor from an URL * * @param url the server url (syntax: rtmp://host:port/app/streamKey) - * @return RTMP connection + * @return RTMP connection descriptor */ - fun fromUrl(url: String): RtmpConnectionDescriptor { - val uri = Uri.parse(url) + fun fromUrl(url: String) = + fromUri(Uri.parse(url)) + /** + * Creates a RTMP connection descriptor from an Uri + * + * @param uri the server Uri + * @return RTMP connection descriptor + */ + fun fromUri(uri: Uri): RtmpMediaDescriptor { val scheme = uri.scheme ?: throw InvalidParameterException("Invalid scheme ${uri.scheme}") val host = uri.host ?: throw InvalidParameterException("Invalid host ${uri.host}") @@ -90,7 +100,7 @@ data class RtmpConnectionDescriptor( val app = uri.pathSegments.minus(uri.lastPathSegment).joinToString("/") val streamKey = uri.lastPathSegment ?: throw InvalidParameterException("Invalid streamKey ${uri.lastPathSegment}") - return RtmpConnectionDescriptor(scheme, host, port, app, streamKey) + return RtmpMediaDescriptor(scheme, host, port, app, streamKey) } } } \ No newline at end of file diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/data/SrtConnectionDescriptor.kt b/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/SrtMediaDescriptor.kt similarity index 65% rename from extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/data/SrtConnectionDescriptor.kt rename to core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/SrtMediaDescriptor.kt index 477549d97..9f5b7573d 100644 --- a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/data/SrtConnectionDescriptor.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/SrtMediaDescriptor.kt @@ -13,14 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.ext.srt.data +package io.github.thibaultbee.streampack.data.mediadescriptor import android.net.Uri +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo import java.security.InvalidParameterException +/** + * Creates a SRT connection descriptor from an [Uri] + * + * @param uri srt server uri + * @param serviceInfo TS service information + */ +fun SrtMediaDescriptor(uri: Uri, serviceInfo: TSServiceInfo = createDefaultTsServiceInfo()) = + SrtMediaDescriptor.fromUri(uri) /** - * SRT connection parameters + * A convenient class for SRT connection parameters. * * If the field is null, it will be ignored. The default SRT parameters will be used (see [default SRT options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md)) * See @@ -31,15 +40,17 @@ import java.security.InvalidParameterException * @param passPhrase SRT passPhrase * @param latency SRT latency in ms * @param connectionTimeout SRT connection timeout in ms + * @param serviceInfo TS service information */ -data class SrtConnectionDescriptor( +class SrtMediaDescriptor( val host: String, val port: Int, val streamId: String? = null, val passPhrase: String? = null, val latency: Int? = null, val connectionTimeout: Int? = null, -) { + serviceInfo: TSServiceInfo = createDefaultTsServiceInfo() +) : MediaDescriptor(listOf(serviceInfo)) { init { require(host.isNotBlank()) { "Invalid host $host" } require( @@ -49,6 +60,24 @@ data class SrtConnectionDescriptor( require(port < 65536) { "Invalid port $port" } } + val uri: Uri = buildUri() + + private fun buildUri(): Uri { + val uriBuilder = Uri.Builder() + .scheme(SRT_SCHEME) + .encodedAuthority("$host:$port") + streamId?.let { uriBuilder.appendQueryParameter(STREAM_ID_QUERY_PARAMETER, it) } + passPhrase?.let { uriBuilder.appendQueryParameter(PASS_PHRASE_QUERY_PARAMETER, it) } + latency?.let { uriBuilder.appendQueryParameter(LATENCY_QUERY_PARAMETER, it.toString()) } + connectionTimeout?.let { + uriBuilder.appendQueryParameter( + CONNECTION_TIMEOUT_QUERY_PARAMETER, + it.toString() + ) + } + return uriBuilder.build() + } + companion object { private const val SRT_SCHEME = "srt" private const val SRT_PREFIX = "$SRT_SCHEME://" @@ -70,18 +99,25 @@ data class SrtConnectionDescriptor( ) /** - * Creates a SRT connection from an URL + * Creates a SRT connection descriptor from an URL * * @param url server url (syntax: srt://host:port?streamid=streamId&passphrase=passPhrase) - * @return SRT connection + * @return SRT connection descriptor + */ + fun fromUrl(url: String) = fromUri(Uri.parse(url)) + + /** + * Creates a SRT connection descriptor from an Uri + * + * @param uri server uri + * @return SRT connection descriptor */ - fun fromUrl(url: String): SrtConnectionDescriptor { - val uri = Uri.parse(url) + fun fromUri(uri: Uri): SrtMediaDescriptor { if (uri.scheme != SRT_SCHEME) { - throw InvalidParameterException("URL $url is not an srt URL") + throw InvalidParameterException("URL $uri is not an srt URL") } val host = uri.host - ?: throw InvalidParameterException("Failed to parse URL $url: unknown host") + ?: throw InvalidParameterException("Failed to parse URL $uri: unknown host") val port = uri.port val streamId = uri.getQueryParameter(STREAM_ID_QUERY_PARAMETER) @@ -90,23 +126,22 @@ data class SrtConnectionDescriptor( val connectionTimeout = uri.getQueryParameter(CONNECTION_TIMEOUT_QUERY_PARAMETER)?.toInt() - val mode = uri.getQueryParameter(MODE_QUERY_PARAMETER) if (mode != null) { - require(mode == "caller") { "Failed to parse URL $url: invalid mode: $mode" } + require(mode == "caller") { "Failed to parse URL $uri: invalid mode: $mode" } } val transtype = uri.getQueryParameter(TRANSTYPE_QUERY_PARAMETER) if (transtype != null) { - require(transtype == "live") { "Failed to parse URL $url: invalid transtype: $transtype" } + require(transtype == "live") { "Failed to parse URL $uri: invalid transtype: $transtype" } } val unknownParameters = uri.queryParameterNames.find { queryParameterList.contains(it).not() } if (unknownParameters != null) { - throw InvalidParameterException("Failed to parse URL $url: unknown parameter(s): $unknownParameters") + throw InvalidParameterException("Failed to parse URL $uri: unknown parameter(s): $unknownParameters") } - return SrtConnectionDescriptor( + return SrtMediaDescriptor( host, port, streamId, @@ -115,30 +150,12 @@ data class SrtConnectionDescriptor( connectionTimeout = connectionTimeout ) } - - /** - * Creates a SRT connection from an URL and given parameters. - * Query parameters are ignored. - * - * @param url server url (syntax: srt://host:port) - * @param streamId SRT stream ID - * @param passPhrase SRT passPhrase - * @return SRT connection - */ - fun fromUrlAndParameters( - url: String, - streamId: String? = null, - passPhrase: String? = null - ): SrtConnectionDescriptor { - val uri = Uri.parse(url) - if (uri.scheme != SRT_SCHEME) { - throw InvalidParameterException("URL $url is not an srt URL") - } - val host = uri.host - ?: throw InvalidParameterException("Failed to parse URL $url: unknown host") - val port = uri.port - - return SrtConnectionDescriptor(host, port, streamId, passPhrase) - } } -} \ No newline at end of file +} + +fun createDefaultTsServiceInfo() = TSServiceInfo( + TSServiceInfo.ServiceType.DIGITAL_TV, + 0x4698, + "Stream", + "StreamPack" +) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/UriMediaDescriptor.kt b/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/UriMediaDescriptor.kt new file mode 100644 index 000000000..0f3cef85d --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/data/mediadescriptor/UriMediaDescriptor.kt @@ -0,0 +1,22 @@ +package io.github.thibaultbee.streampack.data.mediadescriptor + +import android.content.Context +import android.net.Uri +import io.github.thibaultbee.streampack.internal.endpoints.MediaContainerType +import io.github.thibaultbee.streampack.internal.endpoints.MediaSinkType + +fun UriMediaDescriptor(url: String, customData: List = emptyList()) = + UriMediaDescriptor(Uri.parse(url), customData) + +class UriMediaDescriptor(val uri: Uri, customData: List = emptyList()) : + MediaDescriptor(customData) { + val sinkType = MediaSinkType.inferFromUri(uri) + + internal fun getContainerType(context: Context) = + when (sinkType) { + MediaSinkType.FILE -> MediaContainerType.inferFromFileUri(uri) + MediaSinkType.CONTENT -> MediaContainerType.inferFromContentUri(context, uri) + MediaSinkType.SRT -> MediaContainerType.TS + MediaSinkType.RTMP -> MediaContainerType.FLV + } +} diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/DynamicEndpoint.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/DynamicEndpoint.kt new file mode 100644 index 000000000..1d41487d4 --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/DynamicEndpoint.kt @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2024 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.internal.endpoints + +import android.content.Context +import io.github.thibaultbee.streampack.data.Config +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.RtmpMediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.SrtMediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.createDefaultTsServiceInfo +import io.github.thibaultbee.streampack.internal.data.Frame +import io.github.thibaultbee.streampack.internal.endpoints.composites.CompositeEndpoint +import io.github.thibaultbee.streampack.internal.endpoints.composites.CompositeEndpoints +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.FlvMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.ContentSink +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.FileSink +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.ISink +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +/** + * Default implementation of [IEndpoint]. + * + * It creates an [IEndpoint] based on the [MediaDescriptor]. + */ +class DynamicEndpoint( + private val context: Context, + private val factory: Factory = DefaultFactory(context) +) : IEndpoint { + private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Default) + private var _endpoint: IEndpoint? = null + + private val endpoint: IEndpoint + get() { + val endpoint = _endpoint + require(endpoint != null) { "Set an endpoint before trying to write to it" } + return endpoint + } + + + private var _isOpened = MutableStateFlow(false) + + override val isOpened: StateFlow = _isOpened + + /** + * Only available when the endpoint is opened. + */ + override val info: IPublicEndpoint.IEndpointInfo + get() = _endpoint?.info ?: throw IllegalStateException("Endpoint is not opened") + + fun getInfo(descriptor: MediaDescriptor): IPublicEndpoint.IEndpointInfo { + return factory.create(descriptor).info // TODO: to optimize + } + + override suspend fun open(descriptor: MediaDescriptor) { + require(!_isOpened.value) { "Endpoint is already opened" } + + val endpoint = factory.create(descriptor) + coroutineScope.launch { endpoint.isOpened.collect { _isOpened.emit(it) } }//TODO: fix this + endpoint.open(descriptor) + _endpoint = endpoint + _isOpened.emit(true) // TODO: fix this + } + + override fun addStreams(streamConfigs: List) = + endpoint.addStreams(streamConfigs) + + override fun addStream(streamConfig: Config) = endpoint.addStream(streamConfig) + + override suspend fun write(frame: Frame, streamPid: Int) = endpoint.write(frame, streamPid) + + override suspend fun startStream() = endpoint.startStream() + + override suspend fun stopStream() { + _endpoint?.stopStream() + } + + override suspend fun close() { + try { + _endpoint?.close() + } finally { + _endpoint = null + } + } + + override fun release() { + _endpoint?.release() + } + + /** + * Factory to create an [IEndpoint] based on a [MediaDescriptor]. + */ + interface Factory { + + /** + * Create an [IEndpoint] based on a [MediaDescriptor]. + */ + fun create(descriptor: MediaDescriptor): IEndpoint + } + + /** + * Default implementation of [Factory]. + */ + class DefaultFactory(private val context: Context) : Factory { + override fun create(descriptor: MediaDescriptor): IEndpoint { + return when (descriptor) { + is UriMediaDescriptor -> createUriEndpoint(descriptor) + is RtmpMediaDescriptor -> CompositeEndpoints.createRtmpEndpoint() + is SrtMediaDescriptor -> { + val serviceInfo = descriptor.getCustomData(TSServiceInfo::class.java)!! + CompositeEndpoints.createSrtEndpoint(serviceInfo) + } + } + } + + private fun createUriEndpoint( + descriptor: UriMediaDescriptor + ): IEndpoint { + return when (descriptor.sinkType) { + MediaSinkType.FILE -> createUriFileEndpoint(descriptor, FileSink()) + MediaSinkType.CONTENT -> createUriFileEndpoint(descriptor, ContentSink(context)) + MediaSinkType.SRT -> { + val serviceInfo = descriptor.getCustomData(TSServiceInfo::class.java)!! + CompositeEndpoints.createSrtEndpoint(serviceInfo) + } + + MediaSinkType.RTMP -> CompositeEndpoints.createRtmpEndpoint() + } + } + + private fun createUriFileEndpoint(descriptor: UriMediaDescriptor, sink: ISink): IEndpoint { + return when (descriptor.getContainerType(context)) { + MediaContainerType.MP4 -> MediaMuxerEndpoint(context) + MediaContainerType.TS -> { + val serviceInfo = descriptor.getCustomData(TSServiceInfo::class.java) + ?: createDefaultTsServiceInfo() + CompositeEndpoint( + TSMuxer().apply { addService(serviceInfo) }, + sink + ) + } + + MediaContainerType.FLV -> CompositeEndpoint( + FlvMuxer( + isForFile = true + ), sink + ) + } + } + } +} diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/IEndpoint.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/IEndpoint.kt index 5380ad72b..d9791da86 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/IEndpoint.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/IEndpoint.kt @@ -16,29 +16,39 @@ package io.github.thibaultbee.streampack.internal.endpoints import io.github.thibaultbee.streampack.data.Config +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor import io.github.thibaultbee.streampack.internal.data.Frame -import io.github.thibaultbee.streampack.internal.endpoints.sinks.IConnectable -import io.github.thibaultbee.streampack.internal.endpoints.sinks.IFile +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.FileSink import io.github.thibaultbee.streampack.internal.interfaces.Releaseable +import io.github.thibaultbee.streampack.internal.interfaces.SuspendCloseable import io.github.thibaultbee.streampack.internal.interfaces.SuspendStreamable +import kotlinx.coroutines.flow.StateFlow -interface IEndpoint : IPublicEndpoint, SuspendStreamable, Releaseable { +interface IEndpoint : IPublicEndpoint, SuspendStreamable, + SuspendCloseable, Releaseable { + /** + * Opens the endpoint. + * The endpoint must check if the [MediaDescriptor] is supported and if it is not already opened. + * @param descriptor the media descriptor + */ + suspend fun open(descriptor: MediaDescriptor) + /** * Writes a [Frame] to the [IEndpoint]. * * @param frame the [Frame] to write * @param streamPid the stream id the [Frame] belongs to */ - fun write(frame: Frame, streamPid: Int) + suspend fun write(frame: Frame, streamPid: Int) /** * Registers new streams to the [IEndpoint]. * - * @param streamsConfig the list of [Config] to register + * @param streamConfigs the list of [Config] to register * @return the map of [Config] to their corresponding stream id */ - fun addStreams(streamsConfig: List): Map + fun addStreams(streamConfigs: List): Map /** * Registers a new stream to the [IEndpoint]. @@ -50,6 +60,12 @@ interface IEndpoint : IPublicEndpoint, SuspendStreamable, Releaseable { } interface IPublicEndpoint { + /** + * Whether if the endpoint is opened. + * For example, if the file is opened for [FileSink]. + */ + val isOpened: StateFlow + /** * A info to verify supported formats. */ @@ -95,7 +111,3 @@ interface IPublicEndpoint { } } } - -interface IConnectableEndpoint : IEndpoint, IConnectable - -interface IFileEndpoint : IEndpoint, IFile \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaContainerType.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaContainerType.kt new file mode 100644 index 000000000..7cd2e664c --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaContainerType.kt @@ -0,0 +1,35 @@ +package io.github.thibaultbee.streampack.internal.endpoints + +import android.content.Context +import android.media.MediaFormat +import android.net.Uri + +enum class MediaContainerType(val values: Set) { + MP4("mp4"), + TS("ts"), + FLV("flv"); + + constructor(vararg values: String) : this(values.toSet()) + + companion object { + fun inferFromExtension(extension: String): MediaContainerType { + return entries.first { it.values.contains(extension) } + } + + fun inferFromFileUri(uri: Uri): MediaContainerType { + val path = uri.path + val extension = path?.substringAfterLast('.') + ?: throw IllegalArgumentException("No extension found in uri: $uri") + return inferFromExtension(extension) + } + + fun inferFromContentUri(context: Context, uri: Uri): MediaContainerType { + return when (val type = context.contentResolver.getType(uri)) { + "video/mp4" -> MP4 + "video/x-flv" -> FLV + "video/mp2ts" -> TS + else -> throw UnsupportedOperationException("Unsupported content type: $type") + } + } + } +} diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaMuxerEndpoint.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaMuxerEndpoint.kt index 6bf4dfcb9..130b707ef 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaMuxerEndpoint.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaMuxerEndpoint.kt @@ -15,22 +15,29 @@ */ package io.github.thibaultbee.streampack.internal.endpoints +import android.content.Context import android.media.MediaCodec.BUFFER_FLAG_KEY_FRAME import android.media.MediaCodec.BufferInfo import android.media.MediaFormat import android.media.MediaMuxer import android.os.Build +import android.os.ParcelFileDescriptor import io.github.thibaultbee.streampack.data.Config +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor import io.github.thibaultbee.streampack.internal.data.Frame -import java.io.File -import java.io.FileDescriptor -import java.io.OutputStream +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.runBlocking +import java.security.InvalidParameterException /** * An [IEndpoint] implementation of the [MediaMuxer]. */ -class MediaMuxerEndpoint : IEndpoint, IFileEndpoint { +class MediaMuxerEndpoint(private val context: Context) : IEndpoint { private var mediaMuxer: MediaMuxer? = null + private var fileDescriptor: ParcelFileDescriptor? = null + private var isStarted = false /** @@ -41,35 +48,48 @@ class MediaMuxerEndpoint : IEndpoint, IFileEndpoint { override val info = MediaMuxerEndpointInfo - override var file: File? = null - set(value) { - mediaMuxer?.release() - if (value != null) { + private val _isOpened = MutableStateFlow(false) + override val isOpened: StateFlow = _isOpened + + override suspend fun open(descriptor: MediaDescriptor) { + descriptor as UriMediaDescriptor // Only UriMediaDescriptor is supported here + require(!isOpened.value) { "Endpoint is already opened" } + require((descriptor.sinkType == MediaSinkType.FILE) || (descriptor.sinkType == MediaSinkType.CONTENT)) { "MediaDescriptor must have a path" } + + when (descriptor.sinkType) { + MediaSinkType.FILE -> { + val path = descriptor.uri.path + ?: throw IllegalStateException("Could not get path from uri: ${descriptor.uri}") mediaMuxer = - MediaMuxer(value.absolutePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) + MediaMuxer(path, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) } - field = value - } - - override var outputStream: OutputStream? = null - set(_) { - throw UnsupportedOperationException("MediaMuxerEndpoint does not support OutputStream") - } - override var fileDescriptor: FileDescriptor? = null - set(value) { - mediaMuxer?.release() - if (value != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - mediaMuxer = MediaMuxer(value, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) - } else { - throw UnsupportedOperationException("MediaMuxerEndpoint does not support FileDescriptor on this device") - } + MediaSinkType.CONTENT -> { + fileDescriptor = + context.contentResolver.openFileDescriptor( + descriptor.uri, + "w" + )?.apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + mediaMuxer = + MediaMuxer( + this.fileDescriptor, + MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4 + ) + } else { + throw IllegalStateException("Using content sink for API < 26 is not supported. Use file sink instead.") + } + } + ?: throw IllegalStateException("Could not open file descriptor for uri: ${descriptor.uri}") } - field = value + + else -> throw InvalidParameterException("Unsupported sink type: ${descriptor.sinkType}") } - override fun write(frame: Frame, streamPid: Int) { + _isOpened.emit(true) + } + + override suspend fun write(frame: Frame, streamPid: Int) { mediaMuxer?.let { if (streamIdToTrackId.size < numOfStreams) { addTrack(it, streamPid, frame.format) @@ -104,13 +124,13 @@ class MediaMuxerEndpoint : IEndpoint, IFileEndpoint { } } - override fun addStreams(streamsConfig: List): Map { + override fun addStreams(streamConfigs: List): Map { mediaMuxer?.let { /** * We can't addTrack here because we don't have the codec specific data. * We will add it when we receive the first frame. */ - return streamsConfig.associateWith { numOfStreams++ } + return streamConfigs.associateWith { numOfStreams++ } } throw IllegalStateException("MediaMuxer is not initialized") } @@ -136,17 +156,38 @@ class MediaMuxerEndpoint : IEndpoint, IFileEndpoint { override suspend fun stopStream() { try { mediaMuxer?.stop() - } catch (e: IllegalStateException) { - // MediaMuxer is already stopped + } catch (_: IllegalStateException) { + } + + try { + fileDescriptor?.close() + } catch (_: Exception) { + } finally { + fileDescriptor = null + } + + numOfStreams = 0 + streamIdToTrackId.clear() + isStarted = false + } + + override suspend fun close() { + stopStream() + try { + mediaMuxer?.release() + } catch (e: Exception) { + // MediaMuxer is already released } finally { - numOfStreams = 0 - streamIdToTrackId.clear() - isStarted = false + mediaMuxer = null + _isOpened.emit(false) } } override fun release() { - mediaMuxer?.release() + runBlocking { + stopStream() + close() + } } object MediaMuxerEndpointInfo : IPublicEndpoint.IEndpointInfo { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaSinkType.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaSinkType.kt new file mode 100644 index 000000000..0041dc019 --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/MediaSinkType.kt @@ -0,0 +1,33 @@ +package io.github.thibaultbee.streampack.internal.endpoints + +import android.net.Uri + +/** + * Media scheme. + * Use to determine the type of sink. + */ +enum class MediaSinkType(val schemes: Set) { + FILE("file"), + SRT("srt"), + RTMP("rtmp", "rtmps"), + CONTENT("content"); + + constructor(vararg values: String) : this(values.toSet()) + + companion object { + + fun inferFromUri(uri: Uri) = inferFromScheme(uri.scheme) + + fun inferFromScheme(scheme: String?): MediaSinkType { + if (isLocalFileScheme(scheme)) { + return FILE + } + return entries.first { it.schemes.contains(scheme) } + } + + private fun isLocalFileScheme(scheme: String?): Boolean { + return scheme.isNullOrEmpty() || (FILE.schemes.contains(scheme)) + } + } +} + diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/CompositeEndpoint.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/CompositeEndpoint.kt index 8d3160afb..a716b321d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/CompositeEndpoint.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/CompositeEndpoint.kt @@ -16,13 +16,17 @@ package io.github.thibaultbee.streampack.internal.endpoints.composites import io.github.thibaultbee.streampack.data.Config +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor import io.github.thibaultbee.streampack.internal.data.Frame import io.github.thibaultbee.streampack.internal.data.Packet import io.github.thibaultbee.streampack.internal.endpoints.IEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IPublicEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IPublicMuxer -import io.github.thibaultbee.streampack.internal.endpoints.sinks.ISink +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IPublicMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.EndpointConfiguration +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.ISink +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.runBlocking /** * An [IEndpoint] implementation that combines a [IMuxer] and a [ISink]. @@ -30,37 +34,52 @@ import io.github.thibaultbee.streampack.internal.endpoints.sinks.ISink open class CompositeEndpoint(final override val muxer: IMuxer, override val sink: ISink) : ICompositeEndpoint { /** - * The total start bitrate of all streams. + * The video and audio configurations. * It is used to configure the sink. */ - private var bitrate = 0 + private val configurations = mutableListOf() override val info = CompositeEndpointInfo(muxer.info) init { - muxer.listener = object : IMuxer.IMuxerListener { + muxer.listener = object : + IMuxer.IMuxerListener { override fun onOutputFrame(packet: Packet) { - sink.write(packet) + runBlocking { + sink.write(packet) + } } } } - override fun write(frame: Frame, streamPid: Int) = muxer.write(frame, streamPid) + override val isOpened: StateFlow + get() = sink.isOpened - override fun addStreams(streamsConfig: List): Map { - val streamIds = muxer.addStreams(streamsConfig) - bitrate += streamsConfig.sumOf { it.startBitrate } + override suspend fun open(descriptor: MediaDescriptor) { + sink.open(descriptor) + } + + override suspend fun close() { + stopStream() + sink.close() + } + + override suspend fun write(frame: Frame, streamPid: Int) = muxer.write(frame, streamPid) + + override fun addStreams(streamConfigs: List): Map { + val streamIds = muxer.addStreams(streamConfigs) + configurations.addAll(streamConfigs) return streamIds } override fun addStream(streamConfig: Config): Int { val streamId = muxer.addStream(streamConfig) - bitrate += streamConfig.startBitrate + configurations.add(streamConfig) return streamId } override suspend fun startStream() { - sink.configure(bitrate) + sink.configure(EndpointConfiguration(configurations)) sink.startStream() muxer.startStream() } @@ -73,11 +92,14 @@ open class CompositeEndpoint(final override val muxer: IMuxer, override val sink override suspend fun stopStream() { muxer.stopStream() sink.stopStream() - bitrate = 0 + configurations.clear() } override fun release() { - sink.release() + runBlocking { + stopStream() + close() + } } class CompositeEndpointInfo( diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/CompositeEndpoints.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/CompositeEndpoints.kt new file mode 100644 index 000000000..6448614c7 --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/CompositeEndpoints.kt @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.internal.endpoints.composites + +import android.content.Context +import io.github.thibaultbee.streampack.internal.endpoints.IEndpoint +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.FlvMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.ILiveSink + +/** + * An [IEndpoint] implementation that combines a [IMuxer] and a [ISink]. + */ +object CompositeEndpoints { + /** + * Creates an endpoint for SRT (with a TS muxer) + */ + internal fun createSrtEndpoint(serviceInfo: TSServiceInfo): IEndpoint { + val sink = createSrtSink() + return CompositeEndpoint(TSMuxer().apply { addService(serviceInfo) }, sink) + } + + /** + * Creates an endpoint for RTMP (with a FLV muxer) + */ + internal fun createRtmpEndpoint(): IEndpoint { + val sink = createRtmpSink() + return CompositeEndpoint( + FlvMuxer( + isForFile = false + ), sink + ) + } + + private fun createRtmpSink(): ILiveSink { + return try { + val clazz = + Class.forName("io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.composites.sinks.RtmpSink") + clazz.getConstructor().newInstance() as ILiveSink + } catch (e: ClassNotFoundException) { + // Expected if the app was built without the RTMP extension. + throw ClassNotFoundException( + "Attempting to stream RTMP stream without depending on the RTMP extension", + e + ) + } catch (e: Exception) { + // The RTMP extension is present, but instantiation failed. + throw RuntimeException("Error instantiating RTMP extension", e) + } + } + + private fun createSrtSink(): ILiveSink { + return try { + val clazz = + Class.forName("io.github.thibaultbee.streampack.ext.srt.internal.endpoints.composites.sinks.SrtSink") + clazz.getConstructor().newInstance() as ILiveSink + } catch (e: ClassNotFoundException) { + // Expected if the app was built without the SRT extension. + throw ClassNotFoundException( + "Attempting to stream SRT stream without depending on the SRT extension", + e + ) + } catch (e: Exception) { + // The SRT extension is present, but instantiation failed. + throw RuntimeException("Error instantiating SRT extension", e) + } + } +} diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/ConnectableCompositeEndpoint.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/ConnectableCompositeEndpoint.kt deleted file mode 100644 index 037c774de..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/ConnectableCompositeEndpoint.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2024 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.internal.endpoints.composites - -import io.github.thibaultbee.streampack.internal.endpoints.IConnectableEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.sinks.IConnectable -import io.github.thibaultbee.streampack.internal.endpoints.sinks.ILiveSink -import io.github.thibaultbee.streampack.listeners.OnConnectionListener - -/** - * A [CompositeEndpoint] with [IConnectable] capabilities. - */ -class ConnectableCompositeEndpoint(muxer: IMuxer, override val sink: ILiveSink) : - CompositeEndpoint(muxer, sink), IConnectableEndpoint { - - override var onConnectionListener: OnConnectionListener? - get() = sink.onConnectionListener - set(value) { - sink.onConnectionListener = value - } - - override val isConnected: Boolean - get() = sink.isConnected - - override suspend fun connect(url: String) = sink.connect(url) - - override fun disconnect() = sink.disconnect() -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/FileCompositeEndpoint.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/FileCompositeEndpoint.kt deleted file mode 100644 index ffe738beb..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/FileCompositeEndpoint.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2024 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.internal.endpoints.composites - -import io.github.thibaultbee.streampack.internal.endpoints.IFileEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.sinks.IConnectable -import io.github.thibaultbee.streampack.internal.endpoints.sinks.IFileSink -import java.io.File -import java.io.FileDescriptor -import java.io.OutputStream - -/** - * A [CompositeEndpoint] with [IConnectable] capabilities. - */ -class FileCompositeEndpoint(muxer: IMuxer, override val sink: IFileSink) : - CompositeEndpoint(muxer, sink), IFileEndpoint { - override var file: File? - get() = sink.file - set(value) { - sink.file = value - } - override var outputStream: OutputStream? - get() = sink.outputStream - set(value) { - sink.outputStream = value - } - - override var fileDescriptor: FileDescriptor? - get() = sink.fileDescriptor - set(value) { - sink.fileDescriptor = value - } -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/ICompositeEndpoint.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/ICompositeEndpoint.kt index 71cfaf7a9..ae682d616 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/ICompositeEndpoint.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/ICompositeEndpoint.kt @@ -2,8 +2,8 @@ package io.github.thibaultbee.streampack.internal.endpoints.composites import io.github.thibaultbee.streampack.internal.endpoints.IEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IPublicEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IPublicMuxer -import io.github.thibaultbee.streampack.internal.endpoints.sinks.IPublicSink +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IPublicMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.IPublicSink interface ICompositeEndpoint : IEndpoint, IPublicCompositeEndpoint diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/IMuxer.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/IMuxer.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/IMuxer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/IMuxer.kt index f8c8bf5b3..97e84b544 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/IMuxer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/IMuxer.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.internal.data.Frame @@ -21,7 +21,9 @@ import io.github.thibaultbee.streampack.internal.data.Packet import io.github.thibaultbee.streampack.internal.interfaces.Releaseable import io.github.thibaultbee.streampack.internal.interfaces.Streamable -interface IMuxer : IPublicMuxer, Streamable, Releaseable { +interface IMuxer : + IPublicMuxer, Streamable, + Releaseable { var listener: IMuxerListener? interface IMuxerListener { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/FlvMuxer.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/FlvMuxer.kt similarity index 86% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/FlvMuxer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/FlvMuxer.kt index 52d333f98..b68438976 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/FlvMuxer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/FlvMuxer.kt @@ -13,23 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.internal.data.Frame import io.github.thibaultbee.streampack.internal.data.Packet import io.github.thibaultbee.streampack.internal.data.PacketType -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.AVTagsFactory -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.FlvHeader -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.OnMetadata +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.AVTagsFactory +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.FlvHeader +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.OnMetadata import io.github.thibaultbee.streampack.internal.utils.TimeUtils import io.github.thibaultbee.streampack.internal.utils.extensions.isAudio import io.github.thibaultbee.streampack.internal.utils.extensions.isVideo class FlvMuxer( override var listener: IMuxer.IMuxerListener? = null, - private val writeToFile: Boolean, + private val isForFile: Boolean, ) : IMuxer { override val info = FlvMuxerInfo private val streams = mutableListOf() @@ -87,21 +87,29 @@ class FlvMuxer( override fun addStreams(streamsConfig: List): Map { val streamMap = mutableMapOf() - streams.addAll(streamsConfig.map { Stream(it) }) + streams.addAll(streamsConfig.map { + Stream( + it + ) + }) requireStreams() streams.forEachIndexed { index, stream -> streamMap[stream.config] = index } return streamMap } override fun addStream(streamConfig: Config): Int { - streams.add(Stream(streamConfig)) + streams.add( + Stream( + streamConfig + ) + ) requireStreams() return streams.size - 1 } override fun startStream() { // Header - if (writeToFile) { + if (isForFile) { listener?.onOutputFrame( Packet( FlvHeader(hasAudio, hasVideo).write(), diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/FlvMuxerInfo.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/FlvMuxerInfo.kt similarity index 70% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/FlvMuxerInfo.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/FlvMuxerInfo.kt index 28eda287e..191f94c33 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/FlvMuxerInfo.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/FlvMuxerInfo.kt @@ -13,21 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv import android.media.MediaFormat -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IPublicMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.SoundFormat -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.SoundRate -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.SoundSize -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video.CodecID +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IPublicMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.SoundFormat +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.SoundRate +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.SoundSize +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.video.CodecID -object FlvMuxerInfo : IPublicMuxer.IMuxerInfo { +object FlvMuxerInfo : + IPublicMuxer.IMuxerInfo { override val video = VideoFlvMuxerInfo override val audio = AudioFlvMuxerInfo } -object AudioFlvMuxerInfo : IPublicMuxer.IMuxerInfo.IAudioMuxerInfo { +object AudioFlvMuxerInfo : + IPublicMuxer.IMuxerInfo.IAudioMuxerInfo { /** * Get FLV Muxer supported audio encoders list */ @@ -45,7 +47,8 @@ object AudioFlvMuxerInfo : IPublicMuxer.IMuxerInfo.IAudioMuxerInfo { override val supportedByteFormats = SoundSize.entries.map { it.toByteFormat() } } -object VideoFlvMuxerInfo : IPublicMuxer.IMuxerInfo.IVideoMuxerInfo { +object VideoFlvMuxerInfo : + IPublicMuxer.IMuxerInfo.IVideoMuxerInfo { /** * Get FLV Muxer supported video encoders list */ diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/AmfParameter.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/AmfParameter.kt similarity index 72% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/AmfParameter.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/AmfParameter.kt index 0e1af0aa6..338184e0e 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/AmfParameter.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/AmfParameter.kt @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfBoolean -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfInt16 -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfInt32 -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfNumber -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfString +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfBoolean +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfInt16 +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfInt32 +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfNumber +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfString import java.io.IOException import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfContainer.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfContainer.kt similarity index 78% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfContainer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfContainer.kt index 381e933dc..7aeeb08db 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfContainer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfContainer.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.containers +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.containers -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfNamedParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfNamedParameter import java.nio.ByteBuffer open class AmfContainer : AmfParameter() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfEcmaArray.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfEcmaArray.kt similarity index 73% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfEcmaArray.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfEcmaArray.kt index ffdd294ca..2aa4d8216 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfEcmaArray.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfEcmaArray.kt @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.containers +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.containers -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfInt24 -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfInt32 +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfInt24 +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfInt32 import java.nio.ByteBuffer class AmfEcmaArray : AmfContainer() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfObject.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfObject.kt similarity index 77% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfObject.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfObject.kt index f76be1998..953e73bc5 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfObject.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfObject.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.containers +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.containers -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfInt24 +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfInt24 import java.nio.ByteBuffer class AmfObject : AmfContainer() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfBoolean.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfBoolean.kt similarity index 75% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfBoolean.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfBoolean.kt index 6a6634a83..5e2a3c19d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfBoolean.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfBoolean.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType import java.nio.ByteBuffer class AmfBoolean(private val b: Boolean) : AmfParameter() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt16.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt16.kt similarity index 81% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt16.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt16.kt index 0f189a513..bb8818116 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt16.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt16.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter import java.nio.ByteBuffer class AmfInt16(private val s: Short): AmfParameter() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt24.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt24.kt similarity index 82% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt24.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt24.kt index 1bacb1e48..cc64de058 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt24.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt24.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter import io.github.thibaultbee.streampack.internal.utils.extensions.putShort import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt32.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt32.kt similarity index 80% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt32.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt32.kt index 15d88c775..9542924df 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt32.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt32.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter import java.nio.ByteBuffer class AmfInt32(private val i: Int): AmfParameter() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNamedParameter.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNamedParameter.kt similarity index 84% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNamedParameter.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNamedParameter.kt index 10e1e841f..5aa34f59d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNamedParameter.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNamedParameter.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter import java.nio.ByteBuffer class AmfNamedParameter(internal val name: String, internal val v: AmfParameter) : AmfParameter() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNull.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNull.kt similarity index 73% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNull.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNull.kt index 72e8690c9..f3c41339e 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNull.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNull.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType import java.nio.ByteBuffer class AmfNull : AmfParameter() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNumber.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNumber.kt similarity index 74% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNumber.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNumber.kt index 6c34cedf1..d4cd0889c 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNumber.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNumber.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType import java.nio.ByteBuffer class AmfNumber(private val d: Double) : AmfParameter() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfString.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfString.kt similarity index 78% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfString.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfString.kt index 3eb1b2adc..aaabfd9e9 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfString.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfString.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfParameter -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfParameter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType import java.nio.ByteBuffer class AmfString(private val s: String) : AmfParameter() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/AVTagsFactory.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/AVTagsFactory.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/AVTagsFactory.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/AVTagsFactory.kt index ee7bc59ed..ac4b98d7e 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/AVTagsFactory.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/AVTagsFactory.kt @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags import android.media.MediaFormat import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.data.VideoConfig import io.github.thibaultbee.streampack.internal.data.Frame -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video.PacketType -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video.VideoTagFactory +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.video.PacketType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.video.VideoTagFactory import io.github.thibaultbee.streampack.internal.utils.av.buffer.AVCCBufferWriter import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter import io.github.thibaultbee.streampack.internal.utils.av.buffer.PassthroughBufferWriter diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/AudioTag.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/AudioTag.kt similarity index 98% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/AudioTag.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/AudioTag.kt index 9b7755932..8f2c44134 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/AudioTag.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/AudioTag.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags import android.media.AudioFormat import android.media.MediaFormat diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/FlvHeader.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/FlvHeader.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/FlvHeader.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/FlvHeader.kt index 18c48d584..a615fe202 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/FlvHeader.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/FlvHeader.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags import io.github.thibaultbee.streampack.internal.utils.extensions.shl import io.github.thibaultbee.streampack.internal.utils.extensions.toByte diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/FlvTag.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/FlvTag.kt similarity index 96% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/FlvTag.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/FlvTag.kt index 24843c798..472d7976c 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/FlvTag.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/FlvTag.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags import io.github.thibaultbee.streampack.internal.utils.extensions.put import io.github.thibaultbee.streampack.internal.utils.extensions.putInt24 diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/OnMetadata.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/OnMetadata.kt similarity index 90% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/OnMetadata.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/OnMetadata.kt index c2e8eafb8..b0dcda009 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/OnMetadata.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/OnMetadata.kt @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.data.VideoConfig -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.containers.AmfContainer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.containers.AmfEcmaArray -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video.CodecID -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video.ExtendedVideoTag +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.containers.AmfContainer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.containers.AmfEcmaArray +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.video.CodecID +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.video.ExtendedVideoTag import io.github.thibaultbee.streampack.internal.utils.av.FourCCs import io.github.thibaultbee.streampack.logger.Logger import java.io.IOException diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/ExtendedVideoTag.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/ExtendedVideoTag.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/ExtendedVideoTag.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/ExtendedVideoTag.kt index 3bd6d0fbe..3c76b8675 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/ExtendedVideoTag.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/ExtendedVideoTag.kt @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.video import android.media.MediaFormat import android.os.Build -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.FlvTag -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.TagType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.FlvTag +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.TagType import io.github.thibaultbee.streampack.internal.utils.av.FourCCs import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter import io.github.thibaultbee.streampack.internal.utils.extensions.put diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/VideoTag.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/VideoTag.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/VideoTag.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/VideoTag.kt index 8f4e2eba3..36deac6ac 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/VideoTag.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/VideoTag.kt @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.video import android.media.MediaFormat -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.FlvTag -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.TagType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.FlvTag +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.TagType import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter import io.github.thibaultbee.streampack.internal.utils.extensions.put import io.github.thibaultbee.streampack.internal.utils.extensions.putInt24 diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/VideoTagFactory.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/VideoTagFactory.kt similarity index 86% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/VideoTagFactory.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/VideoTagFactory.kt index 8015916e8..3ee75dbcc 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/video/VideoTagFactory.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/video/VideoTagFactory.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.video -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.FlvTag +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags.FlvTag import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter class VideoTagFactory( diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4Muxer.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4Muxer.kt similarity index 80% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4Muxer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4Muxer.kt index 2168aaace..d5840b948 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4Muxer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4Muxer.kt @@ -13,23 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4 +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4 import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.internal.data.Frame import io.github.thibaultbee.streampack.internal.data.Packet -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.FileTypeBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.MovieFragmentRandomAccessBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TrackFragmentRandomAccessBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.AbstractMovieBoxFactory -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.DefaultMP4SegmenterFactory -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.MP4Segmenter -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.MP4SegmenterFactory -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.MovieBoxFactory -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.MovieFragmentBoxFactory -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.Segment -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.Track +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.FileTypeBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.MovieFragmentRandomAccessBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TrackFragmentRandomAccessBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.AbstractMovieBoxFactory +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.DefaultMP4SegmenterFactory +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.MP4Segmenter +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.MP4SegmenterFactory +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.MovieBoxFactory +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.MovieFragmentBoxFactory +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.Segment +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.Track import io.github.thibaultbee.streampack.internal.utils.TimeUtils import io.github.thibaultbee.streampack.internal.utils.extensions.isAudio import io.github.thibaultbee.streampack.internal.utils.extensions.isVideo diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4MuxerInfo.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4MuxerInfo.kt similarity index 90% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4MuxerInfo.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4MuxerInfo.kt index 8e77f2d0b..a1f2ed378 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4MuxerInfo.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4MuxerInfo.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4 +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4 import android.media.MediaFormat -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IPublicMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IPublicMuxer object MP4MuxerInfo : IPublicMuxer.IMuxerInfo { override val audio = AudioMP4MuxerInfo diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AV1CodecConfigurationBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AV1CodecConfigurationBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AV1CodecConfigurationBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AV1CodecConfigurationBox.kt index 2131b1d8f..237dc04f4 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AV1CodecConfigurationBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AV1CodecConfigurationBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.video.av1.AV1CodecConfigurationRecord import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCConfigurationBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCConfigurationBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCConfigurationBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCConfigurationBox.kt index a4770438e..bd382f19d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCConfigurationBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCConfigurationBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.video.avc.AVCDecoderConfigurationRecord import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/BitRateBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/BitRateBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/BitRateBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/BitRateBox.kt index 61e170aa0..7539e528f 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/BitRateBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/BitRateBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/Box.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/Box.kt similarity index 95% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/Box.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/Box.kt index 36cc900e3..1cefcfc86 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/Box.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/Box.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter import io.github.thibaultbee.streampack.internal.utils.extensions.putInt24 diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ChunkOffsetBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ChunkOffsetBox.kt similarity index 95% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ChunkOffsetBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ChunkOffsetBox.kt index a1e7d5243..ad107a1b9 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ChunkOffsetBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ChunkOffsetBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/CleanApertureBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/CleanApertureBox.kt similarity index 90% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/CleanApertureBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/CleanApertureBox.kt index fae594037..30f25dec3 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/CleanApertureBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/CleanApertureBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataEntryBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataEntryBox.kt similarity index 95% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataEntryBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataEntryBox.kt index a3ed08b89..24764da38 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataEntryBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataEntryBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.extensions.putString import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataInformationBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataInformationBox.kt similarity index 90% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataInformationBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataInformationBox.kt index e147be469..fac5c213d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataInformationBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataInformationBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataReferenceBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataReferenceBox.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataReferenceBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataReferenceBox.kt index 2c95b5348..4e86c77e2 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataReferenceBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataReferenceBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ESDSBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ESDSBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ESDSBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ESDSBox.kt index 6e5a27407..bb2639a43 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ESDSBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ESDSBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.descriptors.ESDescriptor import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/FileTypeBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/FileTypeBox.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/FileTypeBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/FileTypeBox.kt index b9a51d222..394da20a3 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/FileTypeBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/FileTypeBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.extensions.putString import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCConfigurationBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCConfigurationBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCConfigurationBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCConfigurationBox.kt index 9c8c61613..1c47c9a46 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCConfigurationBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCConfigurationBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.video.hevc.HEVCDecoderConfigurationRecord import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HandlerBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HandlerBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HandlerBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HandlerBox.kt index 708d28669..272917b1e 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HandlerBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HandlerBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.extensions.putString import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaBox.kt index 9b8b63b9f..86959ca5d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaDataBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaDataBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaDataBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaDataBox.kt index 8123cc92e..873012047 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaDataBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaDataBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaHeaderBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaHeaderBox.kt similarity index 90% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaHeaderBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaHeaderBox.kt index 03b732bf9..83c6c1d47 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaHeaderBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaHeaderBox.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.utils.TimeUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.utils.TimeUtils import io.github.thibaultbee.streampack.internal.utils.extensions.putInt import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaInformationBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaInformationBox.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaInformationBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaInformationBox.kt index e1003a41b..8784ad493 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MediaInformationBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MediaInformationBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieBox.kt index 20521e4fd..87fbfa704 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieExtendsBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieExtendsBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieExtendsBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieExtendsBox.kt index c8bb2c45e..07e3f1fb4 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieExtendsBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieExtendsBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentBox.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentBox.kt index 84b4c8739..73fb08b06 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentHeaderBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentHeaderBox.kt similarity index 90% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentHeaderBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentHeaderBox.kt index 7499692f9..10d4e57df 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentHeaderBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentHeaderBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessBox.kt index efd0d067f..d5c718f28 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessOffsetBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessOffsetBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessOffsetBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessOffsetBox.kt index c0ec64981..945712492 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessOffsetBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessOffsetBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieHeaderBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieHeaderBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieHeaderBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieHeaderBox.kt index 8fd9e8e70..1d81cbfba 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieHeaderBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieHeaderBox.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.utils.TimeUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.utils.TimeUtils import io.github.thibaultbee.streampack.internal.utils.extensions.put3x3Matrix import io.github.thibaultbee.streampack.internal.utils.extensions.putFixed1616 import io.github.thibaultbee.streampack.internal.utils.extensions.putFixed88 diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/NullMediaHeaderBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/NullMediaHeaderBox.kt similarity index 87% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/NullMediaHeaderBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/NullMediaHeaderBox.kt index 2bb1358f9..a7c15fbae 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/NullMediaHeaderBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/NullMediaHeaderBox.kt @@ -13,6 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes class NullMediaHeaderBox : FullBox("nmhd", 0, 0) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/OpusSpecificBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/OpusSpecificBox.kt similarity index 95% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/OpusSpecificBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/OpusSpecificBox.kt index f61648b7a..33a2a124d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/OpusSpecificBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/OpusSpecificBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.audio.opus.IdentificationHeader import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/PixelAspectRatioBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/PixelAspectRatioBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/PixelAspectRatioBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/PixelAspectRatioBox.kt index 0c1fcd5f3..65076d243 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/PixelAspectRatioBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/PixelAspectRatioBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleDescriptionBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleDescriptionBox.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleDescriptionBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleDescriptionBox.kt index adf0df91d..6b64ea109 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleDescriptionBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleDescriptionBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleEntry.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleEntry.kt similarity index 98% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleEntry.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleEntry.kt index fb53db371..f8278530f 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleEntry.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleEntry.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import android.util.Size import io.github.thibaultbee.streampack.internal.utils.extensions.put diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleSizeBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleSizeBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleSizeBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleSizeBox.kt index eaae34413..58d787b3c 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleSizeBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleSizeBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleTableBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleTableBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleTableBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleTableBox.kt index 896658f17..064507da4 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleTableBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleTableBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleToChunkBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleToChunkBox.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleToChunkBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleToChunkBox.kt index bfecf4957..63ba1605b 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleToChunkBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleToChunkBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SyncSampleBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SyncSampleBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SyncSampleBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SyncSampleBox.kt index fbad06137..1e54c5ea3 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SyncSampleBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SyncSampleBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TimeToSampleBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TimeToSampleBox.kt similarity index 96% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TimeToSampleBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TimeToSampleBox.kt index 45718dd0c..6c912069d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TimeToSampleBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TimeToSampleBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackBox.kt index 7b39b77a0..6562acb07 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackExtendsBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackExtendsBox.kt similarity index 81% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackExtendsBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackExtendsBox.kt index 2829f11e1..3e7e43a73 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackExtendsBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackExtendsBox.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.SampleFlags -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.putInt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.SampleFlags +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.putInt import java.nio.ByteBuffer class TrackExtendsBox( diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBox.kt index 2d2542b61..48ea10592 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBox.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBox.kt index 1f7a47bce..524aa1815 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentHeaderBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentHeaderBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentHeaderBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentHeaderBox.kt index 8f4e43dc6..56c831863 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentHeaderBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentHeaderBox.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.SampleFlags -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.putInt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.SampleFlags +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.putInt import java.nio.ByteBuffer class TrackFragmentHeaderBox( diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentRandomAccessBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentRandomAccessBox.kt similarity index 96% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentRandomAccessBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentRandomAccessBox.kt index c5f151e59..5139a1859 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentRandomAccessBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentRandomAccessBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackHeaderBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackHeaderBox.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackHeaderBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackHeaderBox.kt index dbfa3ce6e..7ae665cf5 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackHeaderBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackHeaderBox.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import android.util.Size -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.utils.TimeUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.utils.TimeUtils import io.github.thibaultbee.streampack.internal.utils.extensions.put3x3Matrix import io.github.thibaultbee.streampack.internal.utils.extensions.putFixed1616 import io.github.thibaultbee.streampack.internal.utils.extensions.putFixed88 diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackRunBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackRunBox.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackRunBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackRunBox.kt index b2a0fea6f..18bc9cc88 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackRunBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackRunBox.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.SampleFlags -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.putInt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.SampleFlags +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.putInt import io.github.thibaultbee.streampack.internal.utils.av.buffer.ByteBufferWriter import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TypeMediaHeaderBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TypeMediaHeaderBox.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TypeMediaHeaderBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TypeMediaHeaderBox.kt index 486b9c68e..02c06b4d1 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TypeMediaHeaderBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TypeMediaHeaderBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/VPCodecConfigurationBox.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/VPCodecConfigurationBox.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/VPCodecConfigurationBox.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/VPCodecConfigurationBox.kt index f4daed306..add7ffd07 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/VPCodecConfigurationBox.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/VPCodecConfigurationBox.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes import io.github.thibaultbee.streampack.internal.utils.av.video.vpx.VPCodecConfigurationRecord import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Chunk.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Chunk.kt similarity index 96% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Chunk.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Chunk.kt index 84e17e159..8340bd752 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Chunk.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Chunk.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models import android.media.MediaFormat import io.github.thibaultbee.streampack.internal.data.Frame diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/MovieBoxFactory.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/MovieBoxFactory.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/MovieBoxFactory.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/MovieBoxFactory.kt index 3a66139b2..421bd2380 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/MovieBoxFactory.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/MovieBoxFactory.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.* +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.* abstract class AbstractMovieBoxFactory { abstract fun build(trackChunks: List, dataOffset: Long): Box diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/SampleFlags.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/SampleFlags.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/SampleFlags.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/SampleFlags.kt index fd10ca612..39f594b0e 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/SampleFlags.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/SampleFlags.kt @@ -1,4 +1,4 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models import io.github.thibaultbee.streampack.internal.utils.extensions.put import io.github.thibaultbee.streampack.internal.utils.extensions.shl diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Segment.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Segment.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Segment.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Segment.kt index 75a44cbf3..d8a82587b 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Segment.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Segment.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models import io.github.thibaultbee.streampack.internal.data.Frame -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.MediaDataBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.MediaDataBox import java.nio.ByteBuffer /** diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Segmenter.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Segmenter.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Segmenter.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Segmenter.kt index 89b16d0d2..2a988ee4f 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Segmenter.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Segmenter.kt @@ -1,4 +1,4 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models import io.github.thibaultbee.streampack.internal.data.Frame diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/SegmenterFactory.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/SegmenterFactory.kt similarity index 77% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/SegmenterFactory.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/SegmenterFactory.kt index 656d0772f..2de764feb 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/SegmenterFactory.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/SegmenterFactory.kt @@ -1,4 +1,4 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models abstract class MP4SegmenterFactory { abstract fun build(hasAudio: Boolean, hasVideo: Boolean): MP4Segmenter diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Track.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Track.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Track.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Track.kt index 4e2aa5a7f..ab1db30d5 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/Track.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/Track.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.internal.utils.TimeUtils diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/TrackChunks.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/TrackChunks.kt similarity index 82% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/TrackChunks.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/TrackChunks.kt index 96d7edcbc..12c259767 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/models/TrackChunks.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/models/TrackChunks.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models import android.media.MediaFormat import android.util.Size @@ -21,40 +21,40 @@ import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.data.VideoConfig import io.github.thibaultbee.streampack.internal.data.Frame -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.AV1CodecConfigurationBox2 -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.AV1SampleEntry -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.AVCConfigurationBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.AVCSampleEntry -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.ChunkLargeOffsetBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.DataEntryUrlBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.DataInformationBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.DataReferenceBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.ESDSBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.HEVCConfigurationBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.HEVCSampleEntry -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.MP4AudioSampleEntry -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.MediaBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.MediaHeaderBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.MediaInformationBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.OpusSampleEntry -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.OpusSpecificBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.SampleDescriptionBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.SampleSizeBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.SampleTableBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.SampleToChunkBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.SyncSampleBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TimeToSampleBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TrackBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TrackExtendsBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TrackFragmentBaseMediaDecodeTimeBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TrackFragmentBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TrackFragmentHeaderBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TrackHeaderBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TrackRunBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.VP9SampleEntry -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.VPCodecConfigurationBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.utils.createHandlerBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.utils.createTypeMediaHeaderBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.AV1CodecConfigurationBox2 +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.AV1SampleEntry +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.AVCConfigurationBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.AVCSampleEntry +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.ChunkLargeOffsetBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.DataEntryUrlBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.DataInformationBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.DataReferenceBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.ESDSBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.HEVCConfigurationBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.HEVCSampleEntry +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.MP4AudioSampleEntry +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.MediaBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.MediaHeaderBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.MediaInformationBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.OpusSampleEntry +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.OpusSpecificBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.SampleDescriptionBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.SampleSizeBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.SampleTableBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.SampleToChunkBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.SyncSampleBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TimeToSampleBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TrackBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TrackExtendsBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TrackFragmentBaseMediaDecodeTimeBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TrackFragmentBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TrackFragmentHeaderBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TrackHeaderBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TrackRunBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.VP9SampleEntry +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.VPCodecConfigurationBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.utils.createHandlerBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.utils.createTypeMediaHeaderBox import io.github.thibaultbee.streampack.internal.utils.TimeUtils import io.github.thibaultbee.streampack.internal.utils.av.audio.opus.OpusCsdParser import io.github.thibaultbee.streampack.internal.utils.av.descriptors.AudioSpecificConfigDescriptor diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/utils/ConfigExtensions.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/utils/ConfigExtensions.kt similarity index 72% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/utils/ConfigExtensions.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/utils/ConfigExtensions.kt index 74a94de85..3234aa756 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/utils/ConfigExtensions.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/utils/ConfigExtensions.kt @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.utils +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.utils import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.data.VideoConfig -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.HandlerBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.SoundMediaHeaderBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.TypeMediaHeaderBox -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes.VideoMediaHeaderBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.HandlerBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.SoundMediaHeaderBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.TypeMediaHeaderBox +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes.VideoMediaHeaderBox fun Config.createTypeMediaHeaderBox(): TypeMediaHeaderBox { return when (this) { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/utils/TimeUtils.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/utils/TimeUtils.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/utils/TimeUtils.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/utils/TimeUtils.kt index 3ca3c7d62..304f7388d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/utils/TimeUtils.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/utils/TimeUtils.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.utils +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.utils import java.util.* import java.util.concurrent.TimeUnit diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/README.md b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/README.md similarity index 100% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/README.md rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/README.md diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxer.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxer.kt similarity index 90% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxer.kt index 4dc670a69..697649bc0 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxer.kt @@ -13,35 +13,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts import android.media.MediaCodecInfo import android.media.MediaFormat import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.internal.data.Frame -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Service -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Stream -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Pat -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Pes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Pmt -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Sdt -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.MuxerConst -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.TSConst +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Service +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Stream +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Pat +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Pes +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Pmt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Sdt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.MuxerConst +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.TSConst import io.github.thibaultbee.streampack.internal.utils.av.audio.aac.ADTSFrameWriter import io.github.thibaultbee.streampack.internal.utils.av.audio.aac.LATMFrameWriter import java.nio.ByteBuffer import java.util.MissingFormatArgumentException import kotlin.random.Random -class TSMuxer: IMuxer { +class TSMuxer : IMuxer { override val info = TSMuxerInfo private val tsServices = mutableListOf() private val tsPes = mutableListOf() - override var listener: IMuxer.IMuxerListener? = null + override var listener: IMuxer.IMuxerListener? = + null set(value) { pat.listener = value sdt.listener = value @@ -220,7 +221,7 @@ class TSMuxer: IMuxer { * * @return list of registered services */ - fun getServices(): List { + fun getServices(): List { return tsServices.map { it.info } } @@ -229,7 +230,7 @@ class TSMuxer: IMuxer { * * @param tsServiceInfo new service to add to service list */ - fun addService(tsServiceInfo: TsServiceInfo) { + fun addService(tsServiceInfo: TSServiceInfo) { require(tsServices.none { it.info == tsServiceInfo }) { "Service already exists" } tsServices.add(Service(tsServiceInfo)) @@ -240,7 +241,7 @@ class TSMuxer: IMuxer { * * @param tsServiceInfo service info of service to remove */ - fun removeService(tsServiceInfo: TsServiceInfo) = removeService(getServices(tsServiceInfo)) + fun removeService(tsServiceInfo: TSServiceInfo) = removeService(getServices(tsServiceInfo)) /** * Removes a service and its streams @@ -284,7 +285,7 @@ class TSMuxer: IMuxer { * @param streamsConfig list of config * @return ordered list of stream id */ - fun addStreams(tsServiceInfo: TsServiceInfo, streamsConfig: List) = + fun addStreams(tsServiceInfo: TSServiceInfo, streamsConfig: List) = addStreams(getServices(tsServiceInfo), streamsConfig) @@ -346,7 +347,7 @@ class TSMuxer: IMuxer { * @param tsServiceInfo service info * @param streamsPid list of streams to remove */ - fun removeStreams(tsServiceInfo: TsServiceInfo, streamsPid: List) = + fun removeStreams(tsServiceInfo: TSServiceInfo, streamsPid: List) = removeStreams(getServices(tsServiceInfo), streamsPid.map { getStream(it) }) /** @@ -457,7 +458,7 @@ class TSMuxer: IMuxer { * @param tsServiceInfo service info * @return Service */ - private fun getServices(tsServiceInfo: TsServiceInfo): Service { + private fun getServices(tsServiceInfo: TSServiceInfo): Service { return tsServices.first { it.info == tsServiceInfo } } diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxerInfo.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxerInfo.kt similarity index 77% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxerInfo.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxerInfo.kt index 92f5e6715..bdd3b3934 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxerInfo.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxerInfo.kt @@ -13,17 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts import android.media.MediaFormat -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IPublicMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IPublicMuxer -object TSMuxerInfo : IPublicMuxer.IMuxerInfo { +object TSMuxerInfo : + IPublicMuxer.IMuxerInfo { override val audio = AudioTSMuxerInfo override val video = VideoTSMuxerInfo } -object AudioTSMuxerInfo : IPublicMuxer.IMuxerInfo.IAudioMuxerInfo { +object AudioTSMuxerInfo : + IPublicMuxer.IMuxerInfo.IAudioMuxerInfo { /** * Get TS Muxer supported audio encoders list */ @@ -35,7 +37,8 @@ object AudioTSMuxerInfo : IPublicMuxer.IMuxerInfo.IAudioMuxerInfo { override val supportedByteFormats: List? = null } -object VideoTSMuxerInfo : IPublicMuxer.IMuxerInfo.IVideoMuxerInfo { +object VideoTSMuxerInfo : + IPublicMuxer.IMuxerInfo.IVideoMuxerInfo { /** * Get TS Muxer supported video encoders list */ diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/ITSElement.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/ITSElement.kt similarity index 89% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/ITSElement.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/ITSElement.kt index 06bf53a0a..c81002ca8 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/ITSElement.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/ITSElement.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/Service.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/Service.kt similarity index 77% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/Service.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/Service.kt index aa6ecebc0..dd020ade6 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/Service.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/Service.kt @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Pmt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Pmt class Service( - val info: TsServiceInfo, + val info: TSServiceInfo, var pmt: Pmt? = null, var streams: MutableList = mutableListOf(), var pcrPid: Short? = null diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/Stream.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/Stream.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/Stream.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/Stream.kt index 515327f97..fce1cc5c5 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/Stream.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/Stream.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data import io.github.thibaultbee.streampack.data.Config import io.github.thibaultbee.streampack.internal.utils.extensions.isAudio diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/TsServiceInfo.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/TSServiceInfo.kt similarity index 87% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/TsServiceInfo.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/TSServiceInfo.kt index 9c6886b71..75afbe904 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/data/TsServiceInfo.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/data/TSServiceInfo.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data -data class TsServiceInfo( +data class TSServiceInfo( val type: ServiceType, val id: Short, val name: String, @@ -33,10 +33,7 @@ data class TsServiceInfo( } override fun equals(other: Any?): Boolean { - if ((other as TsServiceInfo).id == id) { - return true - } - return false + return (other as TSServiceInfo).id == id } override fun hashCode(): Int { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/descriptors/AdaptationField.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/descriptors/AdaptationField.kt similarity index 93% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/descriptors/AdaptationField.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/descriptors/AdaptationField.kt index 863805e22..86c042f83 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/descriptors/AdaptationField.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/descriptors/AdaptationField.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.descriptors +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.descriptors -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.ITSElement -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.TSConst +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.ITSElement +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.TSConst import io.github.thibaultbee.streampack.internal.utils.extensions.put import io.github.thibaultbee.streampack.internal.utils.extensions.putShort import io.github.thibaultbee.streampack.internal.utils.extensions.shl diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pat.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pat.kt similarity index 78% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pat.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pat.kt index d2bbbda67..b8828de4f 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pat.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pat.kt @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.ITSElement -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Service +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.ITSElement +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Service import java.nio.ByteBuffer import kotlin.experimental.or class Pat( - listener: IMuxer.IMuxerListener? = null, + listener: io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener? = null, private val services: List, tsId: Short, versionNumber: Byte = 0, diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pes.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pes.kt similarity index 79% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pes.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pes.kt index eecd684d0..5e97e69b0 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pes.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pes.kt @@ -13,19 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets import io.github.thibaultbee.streampack.internal.data.Frame -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Stream -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.descriptors.AdaptationField -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Pes.StreamId.Companion.fromMimeType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Stream +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.descriptors.AdaptationField +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Pes.StreamId.Companion.fromMimeType import io.github.thibaultbee.streampack.internal.utils.TimeUtils import io.github.thibaultbee.streampack.internal.utils.extensions.isAudio import io.github.thibaultbee.streampack.internal.utils.extensions.isVideo class Pes( - muxerListener: IMuxer.IMuxerListener? = null, + muxerListener: io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener? = null, val stream: Stream, private val hasPcr: Boolean, ) : TS(muxerListener, stream.pid) { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/PesHeader.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/PesHeader.kt similarity index 94% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/PesHeader.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/PesHeader.kt index 41ad785cb..bf862ce86 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/PesHeader.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/PesHeader.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.ITSElement -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.TSConst +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.ITSElement +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.TSConst import io.github.thibaultbee.streampack.internal.utils.extensions.put import io.github.thibaultbee.streampack.internal.utils.extensions.putShort import io.github.thibaultbee.streampack.internal.utils.extensions.shl diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pmt.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pmt.kt similarity index 90% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pmt.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pmt.kt index 3d50deb55..1b6dcf2cb 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Pmt.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Pmt.kt @@ -13,21 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets import android.media.MediaCodecInfo import android.media.MediaFormat import io.github.thibaultbee.streampack.data.AudioConfig -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.ITSElement -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Service -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Stream +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.ITSElement +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Service +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Stream import io.github.thibaultbee.streampack.internal.utils.extensions.put import io.github.thibaultbee.streampack.internal.utils.extensions.putShort import java.nio.ByteBuffer class Pmt( - listener: IMuxer.IMuxerListener? = null, + listener: io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener? = null, private val service: Service, var streams: List, pid: Short, diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Psi.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Psi.kt similarity index 86% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Psi.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Psi.kt index 2b447a18e..7f45b1637 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Psi.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Psi.kt @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.CRC32 +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.CRC32 import io.github.thibaultbee.streampack.internal.utils.extensions.put import java.nio.ByteBuffer open class Psi( - listener: IMuxer.IMuxerListener? = null, + listener: io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener? = null, pid: Short, private val tableId: Byte, private val sectionSyntaxIndicator: Boolean = false, diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Sdt.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Sdt.kt similarity index 85% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Sdt.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Sdt.kt index ef3124802..728074a60 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/Sdt.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/Sdt.kt @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.ITSElement -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Service +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.ITSElement +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Service import io.github.thibaultbee.streampack.internal.utils.extensions.put import io.github.thibaultbee.streampack.internal.utils.extensions.putShort import io.github.thibaultbee.streampack.internal.utils.extensions.putString @@ -25,7 +25,7 @@ import java.nio.ByteBuffer class Sdt( - listener: IMuxer.IMuxerListener? = null, + listener: io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener? = null, private val services: List, tsId: Short, private val originalNetworkId: Short = 0xff01.toShort(), diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TS.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TS.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TS.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TS.kt index 5d9a87113..17c54eb89 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TS.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TS.kt @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets import io.github.thibaultbee.streampack.internal.data.SrtPacket -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.MuxerConst -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.TSOutputCallback +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.MuxerConst +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.TSOutputCallback import io.github.thibaultbee.streampack.internal.utils.extensions.toInt import java.nio.ByteBuffer import java.security.InvalidParameterException open class TS( - listener: IMuxer.IMuxerListener? = null, + listener: io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener? = null, val pid: Short, private val transportErrorIndicator: Boolean = false, private val transportPriority: Boolean = false, diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TableHeader.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TableHeader.kt similarity index 92% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TableHeader.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TableHeader.kt index 6942f316e..d0d14a5b8 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TableHeader.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TableHeader.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.ITSElement +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.ITSElement import io.github.thibaultbee.streampack.internal.utils.extensions.put import io.github.thibaultbee.streampack.internal.utils.extensions.shl import io.github.thibaultbee.streampack.internal.utils.extensions.toInt diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/CRC32.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/CRC32.kt similarity index 98% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/CRC32.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/CRC32.kt index 770a08a98..808101c1a 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/CRC32.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/CRC32.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils import java.nio.ByteBuffer diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/MuxerConst.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/MuxerConst.kt similarity index 91% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/MuxerConst.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/MuxerConst.kt index 70a3e560b..3fdc3351a 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/MuxerConst.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/MuxerConst.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils import io.github.thibaultbee.streampack.internal.data.Packet diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/TSConst.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/TSConst.kt similarity index 88% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/TSConst.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/TSConst.kt index 9968e1bd1..b244fd3ad 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/TSConst.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/TSConst.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils object TSConst { const val SYSTEM_CLOCK_FREQ = 27000000 diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/TSOutputCallback.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/TSOutputCallback.kt similarity index 71% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/TSOutputCallback.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/TSOutputCallback.kt index a52fc5ad9..a7cb911a9 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/TSOutputCallback.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/TSOutputCallback.kt @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils import io.github.thibaultbee.streampack.internal.data.SrtPacket -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer -open class TSOutputCallback(var listener: IMuxer.IMuxerListener? = null) { +open class TSOutputCallback(var listener: io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener? = null) { protected fun writePacket(packet: SrtPacket) { packet.buffer.rewind() listener?.onOutputFrame(packet) diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ContentSink.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ContentSink.kt new file mode 100644 index 000000000..fe4daabad --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ContentSink.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.internal.endpoints.composites.sinks + +import android.content.Context +import android.net.Uri +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor +import io.github.thibaultbee.streampack.internal.data.Packet +import io.github.thibaultbee.streampack.internal.endpoints.MediaSinkType +import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import java.io.OutputStream + + +class ContentSink(private val context: Context) : ISink { + private var outputStream: OutputStream? = null + + private val _isOpened = MutableStateFlow(false) + override val isOpened: StateFlow = _isOpened + + override suspend fun open(mediaDescriptor: MediaDescriptor) { + mediaDescriptor as UriMediaDescriptor // Only UriMediaDescriptor is supported here + require(!isOpened.value) { "ContentSink is already opened" } + require(mediaDescriptor.sinkType == MediaSinkType.CONTENT) { "MediaDescriptor must be a content" } + + outputStream = openContent(context, mediaDescriptor.uri) + _isOpened.emit(true) + } + + override fun configure(config: EndpointConfiguration) {} // Nothing to configure + + override suspend fun startStream() { + require(outputStream != null) { "Open the sink before starting the stream" } + } + + override suspend fun write(packet: Packet) { + require(outputStream != null) { "Open the sink before writing" } + outputStream?.write(packet.buffer.toByteArray()) + } + + override suspend fun stopStream() { + outputStream?.flush() + } + + override suspend fun close() { + stopStream() + try { + outputStream?.close() + } catch (e: Exception) { + // Ignore + } finally { + outputStream = null + _isOpened.emit(false) + } + } + + companion object { + + private fun openContent(context: Context, uri: Uri): OutputStream { + return context.contentResolver.openOutputStream(uri) + ?: throw Exception("Cannot open content: $uri") + } + } +} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/FakeSink.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/FakeSink.kt similarity index 57% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/FakeSink.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/FakeSink.kt index 2b86e0c03..5284af405 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/FakeSink.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/FakeSink.kt @@ -13,33 +13,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.sinks +package io.github.thibaultbee.streampack.internal.endpoints.composites.sinks import io.github.thibaultbee.streampack.internal.data.Packet +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor import io.github.thibaultbee.streampack.logger.Logger +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow /** * A fake endpoint for test purpose. */ class FakeSink : ISink { - override fun configure(config: Int) { - Logger.d(TAG, "configure called with bitrate = $config") + private val _isOpened = MutableStateFlow(false) + + override val isOpened: StateFlow = _isOpened + + override suspend fun open(mediaDescriptor: MediaDescriptor) { + require(!isOpened.value) { "FakeSink is already opened" } + + Logger.d(TAG, "open called: $mediaDescriptor") + _isOpened.emit(true) } - override fun write(packet: Packet) { + override fun configure(config: EndpointConfiguration) { + Logger.d(TAG, "configure called") + } + + override suspend fun write(packet: Packet) { Logger.d(TAG, "write called (packet size = ${packet.buffer.remaining()})") } override suspend fun startStream() { Logger.d(TAG, "startStream called") } - + override suspend fun stopStream() { Logger.d(TAG, "stopStream called") } - override fun release() { - Logger.d(TAG, "release called") + override suspend fun close() { + Logger.d(TAG, "close called") + _isOpened.emit(false) } companion object { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/FileSink.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/FileSink.kt new file mode 100644 index 000000000..491f0a5c3 --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/FileSink.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.internal.endpoints.composites.sinks + +import android.net.Uri +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor +import io.github.thibaultbee.streampack.internal.data.Packet +import io.github.thibaultbee.streampack.internal.endpoints.MediaSinkType +import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import java.io.RandomAccessFile + + +class FileSink : ISink { + private var file: RandomAccessFile? = null + + private val _isOpened = MutableStateFlow(false) + override val isOpened: StateFlow = _isOpened + + override suspend fun open(mediaDescriptor: MediaDescriptor) { + mediaDescriptor as UriMediaDescriptor // Only UriMediaDescriptor is supported here + require(!isOpened.value) { "FileSink is already opened" } + require(mediaDescriptor.sinkType == MediaSinkType.FILE) { "MediaDescriptor must be a file" } + + file = openLocalFile(mediaDescriptor.uri) + _isOpened.emit(true) + } + + override fun configure(config: EndpointConfiguration) {} // Nothing to configure + + override suspend fun startStream() { + require(file != null) { "Set a file before trying to write it" } + } + + override suspend fun write(packet: Packet) { + val file = file + require(file != null) { "Set a file before trying to write it" } + file.write(packet.buffer.toByteArray()) + } + + override suspend fun stopStream() { + // Nothing to do + } + + override suspend fun close() { + try { + file?.close() + } catch (e: Exception) { + // Ignore + } finally { + file = null + _isOpened.emit(false) + } + } + + companion object { + + private fun openLocalFile(uri: Uri): RandomAccessFile { + return RandomAccessFile(uri.path, "rw") + } + } +} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/ILiveSink.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ILiveSink.kt similarity index 62% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/ILiveSink.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ILiveSink.kt index a8d8e0bd2..3536e474a 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/ILiveSink.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ILiveSink.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.sinks +package io.github.thibaultbee.streampack.internal.endpoints.composites.sinks import io.github.thibaultbee.streampack.listeners.OnConnectionListener @@ -24,24 +24,4 @@ interface IConnectable { * Listener to manage connection. */ var onConnectionListener: OnConnectionListener? - - /** - * Whether if the endpoint is connected to the server. - */ - val isConnected: Boolean - - /** - * Connects to a server. - * - * @param url server url - * @throws Exception if connection has failed or configuration has failed - */ - suspend fun connect(url: String) - - /** - * Disconnects from the remote server. - * - * @throws Exception is not connected - */ - fun disconnect() } \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/ISink.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ISink.kt similarity index 54% rename from core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/ISink.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ISink.kt index 8bbf49fa0..065cc0a99 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/ISink.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/ISink.kt @@ -13,20 +13,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.sinks +package io.github.thibaultbee.streampack.internal.endpoints.composites.sinks import io.github.thibaultbee.streampack.internal.data.Packet +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor import io.github.thibaultbee.streampack.internal.interfaces.Configurable -import io.github.thibaultbee.streampack.internal.interfaces.Releaseable +import io.github.thibaultbee.streampack.internal.interfaces.SuspendCloseable import io.github.thibaultbee.streampack.internal.interfaces.SuspendStreamable +import kotlinx.coroutines.flow.StateFlow -interface ISink : IPublicSink, SuspendStreamable, Configurable, Releaseable { +interface ISink : IPublicSink, Configurable, SuspendStreamable, + SuspendCloseable { + /** + * Opens the endpoint. + * @param mediaDescriptor the media descriptor + */ + suspend fun open(mediaDescriptor: MediaDescriptor) /** * Writes a buffer to the [ISink]. * @param packet buffer to write */ - fun write(packet: Packet) + suspend fun write(packet: Packet) } -interface IPublicSink \ No newline at end of file +interface IPublicSink { + /** + * Whether if the endpoint is opened. + * For example, if the file is opened for [FileSink]. + */ + val isOpened: StateFlow +} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/listeners/OnErrorListener.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/SinkConfiguration.kt similarity index 65% rename from core/src/main/java/io/github/thibaultbee/streampack/listeners/OnErrorListener.kt rename to core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/SinkConfiguration.kt index 7a29315ad..866af0b2b 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/listeners/OnErrorListener.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/composites/sinks/SinkConfiguration.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Thibault B. + * Copyright (C) 2024 Thibault B. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,16 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.listeners +package io.github.thibaultbee.streampack.internal.endpoints.composites.sinks + +import io.github.thibaultbee.streampack.data.Config /** - * Interface of Streamer listener + * Internal class to configure [ISink]. */ -interface OnErrorListener { - /** - * Called when an error occurs in a Streamer. - * - * @param e a [Exception] describing what happened - */ - fun onError(e: Exception) -} \ No newline at end of file +data class EndpointConfiguration(val streamConfigs: List) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/FileSink.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/FileSink.kt deleted file mode 100644 index 2f3375d22..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/FileSink.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.internal.endpoints.sinks - -import io.github.thibaultbee.streampack.internal.data.Packet -import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray -import java.io.File -import java.io.FileDescriptor -import java.io.FileOutputStream -import java.io.OutputStream - - -class FileSink : IFileSink { - override var file: File? = null - set(value) { - outputStream = if (value != null) { - FileOutputStream(value, false) - } else { - outputStream?.close() - null - } - field = value - } - - override var outputStream: OutputStream? = null - - override var fileDescriptor: FileDescriptor? = null - set(value) { - outputStream = if (value != null) { - FileOutputStream(value) - } else { - outputStream?.close() - null - } - field = value - } - - override suspend fun startStream() { - if (outputStream == null) { - throw UnsupportedOperationException("Set a file before trying to write it") - } - } - - override fun configure(config: Int) {} // Nothing to configure - - override fun write(packet: Packet) { - outputStream?.write(packet.buffer.toByteArray()) - ?: throw UnsupportedOperationException("Set a file before trying to write it") - } - - override suspend fun stopStream() { - outputStream?.close() - outputStream = null - } - - override fun release() { - } -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/IFileSink.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/IFileSink.kt deleted file mode 100644 index f29344d99..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/endpoints/sinks/IFileSink.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.internal.endpoints.sinks - -import java.io.File -import java.io.FileDescriptor -import java.io.OutputStream - -interface IFileSink : IFile, ISink - -interface IFile { - /** - * The file to record to. - */ - var file: File? - - /** - * The output stream to record to. - */ - var outputStream: OutputStream? - - /** - * The file descriptor to record to. - */ - var fileDescriptor: FileDescriptor? -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/events/EventHandler.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/events/EventHandler.kt deleted file mode 100644 index 58bdcdcf7..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/events/EventHandler.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.internal.events - -import android.os.Handler -import android.os.Looper -import android.os.Message -import io.github.thibaultbee.streampack.error.StreamPackError -import io.github.thibaultbee.streampack.listeners.OnErrorListener - -abstract class EventHandler { - private val eventHandler by lazy { - EventHandler() - } - - protected abstract val onInternalErrorListener: OnErrorListener - - fun reportError(error: StreamPackError) { - val msg = eventHandler.obtainMessage(MSG_ERROR, error) - eventHandler.sendMessage(msg) - } - - companion object { - private const val MSG_ERROR = 0 - } - - open inner class EventHandler( - looper: Looper = Looper.myLooper() ?: Looper.getMainLooper() - ) : Handler(looper) { - override fun handleMessage(msg: Message) { - when (msg.what) { - MSG_ERROR -> onInternalErrorListener.onError( - msg.obj as StreamPackError - ) - } - } - } -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/interfaces/Streamable.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/interfaces/Streamable.kt index 1ef81ecd0..9f912b7a6 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/interfaces/Streamable.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/interfaces/Streamable.kt @@ -44,6 +44,13 @@ interface SuspendStreamable { suspend fun stopStream() } +interface SuspendCloseable { + /** + * Closes and releases resources + */ + suspend fun close() +} + interface Configurable { /** * Configure the [Configurable] implementation. diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/sources/video/camera/CameraSettings.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/sources/video/camera/CameraSettings.kt index b9b9d2f16..d912c93ac 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/sources/video/camera/CameraSettings.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/sources/video/camera/CameraSettings.kt @@ -34,7 +34,7 @@ import io.github.thibaultbee.streampack.internal.utils.extensions.isNormalized import io.github.thibaultbee.streampack.internal.utils.extensions.normalize import io.github.thibaultbee.streampack.internal.utils.extensions.rotate import io.github.thibaultbee.streampack.logger.Logger -import io.github.thibaultbee.streampack.streamers.bases.BaseCameraStreamer +import io.github.thibaultbee.streampack.streamers.DefaultCameraStreamer import io.github.thibaultbee.streampack.utils.getAutoExposureModes import io.github.thibaultbee.streampack.utils.getAutoFocusModes import io.github.thibaultbee.streampack.utils.getAutoWhiteBalanceModes @@ -57,7 +57,7 @@ import java.util.concurrent.TimeUnit /** * Use to change camera settings. - * This object is returned by [BaseCameraStreamer.videoSource.settings]. + * This object is returned by [DefaultCameraStreamer.videoSource.settings]. */ class CameraSettings(context: Context, cameraController: CameraController) { /** diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/sources/video/screen/ScreenSource.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/sources/video/screen/ScreenSource.kt index 9e510ccf0..252e51399 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/sources/video/screen/ScreenSource.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/sources/video/screen/ScreenSource.kt @@ -33,8 +33,10 @@ import io.github.thibaultbee.streampack.internal.sources.video.IVideoSource import io.github.thibaultbee.streampack.internal.utils.extensions.isDevicePortrait import io.github.thibaultbee.streampack.internal.utils.extensions.landscapize import io.github.thibaultbee.streampack.internal.utils.extensions.portraitize -import io.github.thibaultbee.streampack.listeners.OnErrorListener import io.github.thibaultbee.streampack.logger.Logger +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.runBlocking import java.nio.ByteBuffer class ScreenSource( @@ -52,12 +54,14 @@ class ScreenSource( private var mediaProjection: MediaProjection? = null var activityResult: ActivityResult? = null - var onErrorListener: OnErrorListener? = null + + private val _exception = MutableStateFlow(null) + val exception: StateFlow = _exception /** * Avoid to trigger `onError` when screen source `stopStream` has been called. */ - private var isExplicitelyStopped = false + private var isStoppedByUser = false private val mediaProjectionManager = context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager @@ -75,8 +79,10 @@ class ScreenSource( super.onStopped() Logger.i(TAG, "onStopped") - if (!isExplicitelyStopped) { - onErrorListener?.onError(StreamPackError("Screen source virtual display has been stopped")) + if (!isStoppedByUser) { + runBlocking { + _exception.emit(StreamPackError("Screen source virtual display has been stopped")) + } } } } @@ -86,8 +92,10 @@ class ScreenSource( super.onStop() Logger.i(TAG, "onStop") - if (!isExplicitelyStopped) { - onErrorListener?.onError(StreamPackError("Screen source media projection has been stopped")) + if (!isStoppedByUser) { + runBlocking { + _exception.emit(StreamPackError("Screen source media projection has been stopped")) + } } } } @@ -109,7 +117,7 @@ class ScreenSource( val resultCode = activityResult!!.resultCode val resultData = activityResult!!.data!! - isExplicitelyStopped = false + isStoppedByUser = false val orientedSize = orientationProvider.getOrientedSize(videoConfig!!.resolution) mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData).apply { @@ -129,7 +137,7 @@ class ScreenSource( override fun stopStream() { - isExplicitelyStopped = true + isStoppedByUser = true virtualDisplay?.release() virtualDisplay = null diff --git a/core/src/main/java/io/github/thibaultbee/streampack/internal/utils/extensions/ContextExtensions.kt b/core/src/main/java/io/github/thibaultbee/streampack/internal/utils/extensions/ContextExtensions.kt index ef8619237..b91572432 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/internal/utils/extensions/ContextExtensions.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/internal/utils/extensions/ContextExtensions.kt @@ -21,8 +21,6 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT import android.hardware.display.DisplayManager import android.view.Display import android.view.Surface -import io.github.thibaultbee.streampack.R -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo import io.github.thibaultbee.streampack.utils.OrientationUtils /** @@ -63,11 +61,3 @@ val Context.isDevicePortrait: Boolean */ val Context.isDeviceLandscape: Boolean get() = resources.configuration.orientation == ORIENTATION_LANDSCAPE - -val Context.defaultTsServiceInfo - get() = TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, - 0x4698, - getString(R.string.ts_service_default_name), - getString(R.string.ts_service_default_provider_name) - ) diff --git a/core/src/main/java/io/github/thibaultbee/streampack/listeners/OnConnectionListener.kt b/core/src/main/java/io/github/thibaultbee/streampack/listeners/OnConnectionListener.kt index 5ec88caf3..0d368751d 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/listeners/OnConnectionListener.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/listeners/OnConnectionListener.kt @@ -26,16 +26,4 @@ interface OnConnectionListener { * @param message message that described the reason why the connection has been lost. */ fun onLost(message: String) - - /** - * Called when a connection failed. - * - * @param message message that described the reason why the connection has failed. - */ - fun onFailed(message: String) - - /** - * Called when a connection just succeeded. - */ - fun onSuccess() } \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseAudioOnlyStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultAudioOnlyStreamer.kt similarity index 74% rename from core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseAudioOnlyStreamer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultAudioOnlyStreamer.kt index 1fdf10e82..8601778fa 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseAudioOnlyStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultAudioOnlyStreamer.kt @@ -13,24 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.streamers.bases +package io.github.thibaultbee.streampack.streamers import android.content.Context +import io.github.thibaultbee.streampack.internal.endpoints.DynamicEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IEndpoint import io.github.thibaultbee.streampack.internal.sources.audio.MicrophoneSource /** - * A [BaseStreamer] that sends only microphone frames. + * A [DefaultStreamer] that sends only microphone frames. * * @param context application context * @param internalEndpoint the [IEndpoint] implementation */ -open class BaseAudioOnlyStreamer( +open class DefaultAudioOnlyStreamer( context: Context, - internalEndpoint: IEndpoint, -) : BaseStreamer( + internalEndpoint: IEndpoint = DynamicEndpoint(context) +) : DefaultStreamer( context = context, internalVideoSource = null, internalAudioSource = MicrophoneSource(), - internalEndpoint = internalEndpoint, + internalEndpoint = internalEndpoint ) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseCameraStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultCameraStreamer.kt similarity index 71% rename from core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseCameraStreamer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultCameraStreamer.kt index 523862494..36444be8e 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseCameraStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultCameraStreamer.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.streamers.bases +package io.github.thibaultbee.streampack.streamers import android.Manifest import android.content.Context @@ -21,36 +21,37 @@ import android.view.Surface import android.view.SurfaceView import android.view.TextureView import androidx.annotation.RequiresPermission +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor import io.github.thibaultbee.streampack.error.StreamPackError +import io.github.thibaultbee.streampack.internal.endpoints.DynamicEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IEndpoint import io.github.thibaultbee.streampack.internal.sources.audio.MicrophoneSource import io.github.thibaultbee.streampack.internal.sources.video.camera.CameraSource import io.github.thibaultbee.streampack.internal.sources.video.camera.IPublicCameraSource import io.github.thibaultbee.streampack.streamers.helpers.CameraStreamerConfigurationInfo +import io.github.thibaultbee.streampack.streamers.helpers.IConfigurationInfo import io.github.thibaultbee.streampack.streamers.interfaces.ICameraStreamer import kotlinx.coroutines.runBlocking /** - * A [BaseStreamer] that sends microphone and camera frames. + * A [DefaultStreamer] that sends microphone and camera frames. * * @param context application context - * @param enableAudio [Boolean.true] to capture audio + * @param enableMicrophone [Boolean.true] to capture audio * @param internalEndpoint the [IEndpoint] implementation */ -open class BaseCameraStreamer( +open class DefaultCameraStreamer( private val context: Context, - enableAudio: Boolean = true, - internalEndpoint: IEndpoint -) : BaseStreamer( + enableMicrophone: Boolean = true, + internalEndpoint: IEndpoint = DynamicEndpoint(context) +) : DefaultStreamer( context = context, internalVideoSource = CameraSource(context), - internalAudioSource = if (enableAudio) MicrophoneSource() else null, + internalAudioSource = if (enableMicrophone) MicrophoneSource() else null, internalEndpoint = internalEndpoint ), ICameraStreamer { private val internalCameraSource = internalVideoSource as CameraSource - override val info = CameraStreamerConfigurationInfo(internalEndpoint.info) - /** * Gets the camera source. * It allows to configure camera settings and to set the camera id. @@ -79,9 +80,32 @@ open class BaseCameraStreamer( videoSource.cameraId = value } + /** + * Gets configuration information. + * + * When using the [DynamicEndpoint], the endpoint type is unknown until [open] is called. + * In this case, prefer using [getInfo] with the [MediaDescriptor] used in [open]. + */ + override val info: IConfigurationInfo + get() = CameraStreamerConfigurationInfo(endpoint.info) + + /** + * Gets configuration information from [MediaDescriptor]. + * + * @param descriptor the media descriptor + */ + override fun getInfo(descriptor: MediaDescriptor): IConfigurationInfo { + val endpointInfo = if (endpoint is DynamicEndpoint) { + (endpoint as DynamicEndpoint).getInfo(descriptor) + } else { + endpoint.info + } + return CameraStreamerConfigurationInfo(endpointInfo) + } + /** * Starts audio and video capture. - * [BaseStreamer.configure] must have been called at least once. + * [DefaultStreamer.configure] must have been called at least once. * * Inside, it launches both camera and microphone capture. * @@ -120,7 +144,7 @@ open class BaseCameraStreamer( } /** - * Same as [BaseStreamer.release] but it also calls [stopPreview]. + * Same as [DefaultStreamer.release] but it also calls [stopPreview]. */ override fun release() { stopPreview() diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseScreenRecorderStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultScreenRecorderStreamer.kt similarity index 77% rename from core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseScreenRecorderStreamer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultScreenRecorderStreamer.kt index f3fe5e52d..b6d7941eb 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseScreenRecorderStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultScreenRecorderStreamer.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.streamers.bases +package io.github.thibaultbee.streampack.streamers import android.content.Context import android.content.Intent @@ -21,29 +21,37 @@ import android.media.projection.MediaProjectionManager import androidx.activity.ComponentActivity import androidx.activity.result.ActivityResult import androidx.core.app.ActivityCompat +import io.github.thibaultbee.streampack.internal.endpoints.DynamicEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IEndpoint import io.github.thibaultbee.streampack.internal.sources.audio.MicrophoneSource import io.github.thibaultbee.streampack.internal.sources.video.screen.ScreenSource +import kotlinx.coroutines.runBlocking /** - * A [BaseStreamer] that sends microphone and screen frames. + * A [DefaultStreamer] that sends microphone and screen frames. * * @param context application context - * @param enableAudio [Boolean.true] to capture audio + * @param enableMicrophone [Boolean.true] to capture audio * @param internalEndpoint the [IEndpoint] implementation */ -open class BaseScreenRecorderStreamer( +open class DefaultScreenRecorderStreamer( context: Context, - enableAudio: Boolean = true, - internalEndpoint: IEndpoint -) : BaseStreamer( + enableMicrophone: Boolean = true, + internalEndpoint: IEndpoint = DynamicEndpoint(context) +) : DefaultStreamer( context = context, internalVideoSource = ScreenSource(context), - internalAudioSource = if (enableAudio) MicrophoneSource() else null, + internalAudioSource = if (enableMicrophone) MicrophoneSource() else null, internalEndpoint = internalEndpoint ) { private val screenSource = - (internalVideoSource as ScreenSource).apply { onErrorListener = onInternalErrorListener } + (internalVideoSource as ScreenSource).apply { + runBlocking { + exception.collect { + this@DefaultScreenRecorderStreamer._exception.emit(it) + } + } + } companion object { /** @@ -80,7 +88,7 @@ open class BaseScreenRecorderStreamer( } /** - * Same as [BaseStreamer] but it prepares [ScreenSource.encoderSurface]. + * Same as [DefaultStreamer] but it prepares [ScreenSource.encoderSurface]. * You must have set [activityResult] before. */ override suspend fun startStream() { diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultStreamer.kt similarity index 78% rename from core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseStreamer.kt rename to core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultStreamer.kt index db2c4cfc3..097aed6a1 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/bases/BaseStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/DefaultStreamer.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.streamers.bases +package io.github.thibaultbee.streampack.streamers import android.Manifest import android.content.Context @@ -21,6 +21,7 @@ import android.view.Surface import androidx.annotation.RequiresPermission import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.Config +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor import io.github.thibaultbee.streampack.data.VideoConfig import io.github.thibaultbee.streampack.error.StreamPackError import io.github.thibaultbee.streampack.internal.data.Frame @@ -29,21 +30,26 @@ import io.github.thibaultbee.streampack.internal.encoders.IPublicEncoder import io.github.thibaultbee.streampack.internal.encoders.mediacodec.AudioEncoderConfig import io.github.thibaultbee.streampack.internal.encoders.mediacodec.MediaCodecEncoder import io.github.thibaultbee.streampack.internal.encoders.mediacodec.VideoEncoderConfig +import io.github.thibaultbee.streampack.internal.endpoints.DynamicEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IPublicEndpoint -import io.github.thibaultbee.streampack.internal.events.EventHandler import io.github.thibaultbee.streampack.internal.gl.CodecSurface import io.github.thibaultbee.streampack.internal.sources.audio.IAudioSource import io.github.thibaultbee.streampack.internal.sources.audio.IPublicAudioSource import io.github.thibaultbee.streampack.internal.sources.video.IPublicVideoSource import io.github.thibaultbee.streampack.internal.sources.video.IVideoSource -import io.github.thibaultbee.streampack.listeners.OnErrorListener import io.github.thibaultbee.streampack.logger.Logger import io.github.thibaultbee.streampack.streamers.helpers.IConfigurationInfo import io.github.thibaultbee.streampack.streamers.helpers.StreamerConfigurationInfo -import io.github.thibaultbee.streampack.streamers.interfaces.IStreamer +import io.github.thibaultbee.streampack.streamers.interfaces.ICoroutineStreamer +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import java.nio.ByteBuffer +import java.util.concurrent.Executors /** @@ -53,19 +59,18 @@ import java.nio.ByteBuffer * @param internalVideoSource the video source * @param internalAudioSource the audio source * @param internalEndpoint the [IEndpoint] implementation + * @param dispatcher the [CoroutineDispatcher] to execute suspendable methods. For test only. Do not change. */ -abstract class BaseStreamer( +open class DefaultStreamer( private val context: Context, protected val internalAudioSource: IAudioSource?, protected val internalVideoSource: IVideoSource?, - protected val internalEndpoint: IEndpoint, -) : EventHandler(), IStreamer { - /** - * Listener that reports streamer error. - * Supports only one listener. - */ - override var onErrorListener: OnErrorListener? = null - override val info = StreamerConfigurationInfo(internalEndpoint.info) + protected val internalEndpoint: IEndpoint = DynamicEndpoint(context), + private val dispatcher: CoroutineDispatcher = Executors.newSingleThreadExecutor() + .asCoroutineDispatcher() +) : ICoroutineStreamer { + protected val _exception = MutableStateFlow(null) + override val exception: StateFlow = _exception private var audioStreamId: Int? = null private var videoStreamId: Int? = null @@ -76,16 +81,6 @@ abstract class BaseStreamer( private val sourceOrientationProvider = internalVideoSource?.orientationProvider - // Only handle stream error (error on muxer, endpoint,...) - /** - * Internal usage only - */ - final override val onInternalErrorListener = object : OnErrorListener { - override fun onError(e: Exception) { - onStreamError(e) - } - } - private val audioEncoderListener = object : IEncoder.IListener { override fun onError(e: Exception) { onStreamError(e) @@ -94,7 +89,10 @@ abstract class BaseStreamer( override fun onOutputFrame(frame: Frame) { audioStreamId?.let { try { - this@BaseStreamer.internalEndpoint.write(frame, it) + // TODO: use streamer as scope + runBlocking { + this@DefaultStreamer.internalEndpoint.write(frame, it) + } } catch (e: Exception) { throw StreamPackError(e) } @@ -116,7 +114,10 @@ abstract class BaseStreamer( } else { null } - this@BaseStreamer.internalEndpoint.write(frame, it) + // TODO: use streamer as scope + runBlocking { + this@DefaultStreamer.internalEndpoint.write(frame, it) + } } catch (e: Exception) { // Send exception to encoder throw StreamPackError(e) @@ -139,7 +140,9 @@ abstract class BaseStreamer( } catch (e: Exception) { Logger.e(TAG, "onStreamError: Can't stop stream") } finally { - onErrorListener?.onError(e) + runBlocking { + _exception.emit(e) + } } } @@ -188,6 +191,13 @@ abstract class BaseStreamer( override val endpoint: IPublicEndpoint get() = internalEndpoint + override val isOpened: StateFlow + get() = internalEndpoint.isOpened + + + private val _isStreaming = MutableStateFlow(false) + override val isStreaming: StateFlow = _isStreaming + /** * Whether the streamer has audio. */ @@ -198,9 +208,35 @@ abstract class BaseStreamer( */ val hasVideo = internalVideoSource != null + /** + * Gets configuration information. + * + * When using the [DynamicEndpoint], the endpoint type is unknown until [open] is called. + * In this case, prefer using [getInfo] with the [MediaDescriptor] used in [open]. + */ + override val info: IConfigurationInfo + get() = StreamerConfigurationInfo(endpoint.info) + + /** + * Gets configuration information from [MediaDescriptor]. + * + * If the endpoint is not [DynamicEndpoint], [descriptor] is unused as the endpoint type is + * already known. + * + * @param descriptor the media descriptor + */ + override fun getInfo(descriptor: MediaDescriptor): IConfigurationInfo { + val endpointInfo = if (endpoint is DynamicEndpoint) { + (endpoint as DynamicEndpoint).getInfo(descriptor) + } else { + endpoint.info + } + return StreamerConfigurationInfo(endpointInfo) + } + /** * Configures audio settings. - * It is the first method to call after a [BaseStreamer] instantiation. + * It is the first method to call after a [DefaultStreamer] instantiation. * It must be call when both stream and audio capture are not running. * * Use [IConfigurationInfo] to get value limits. @@ -285,7 +321,7 @@ abstract class BaseStreamer( /** * Configures video settings. - * It is the first method to call after a [BaseStreamer] instantiation. + * It is the first method to call after a [DefaultStreamer] instantiation. * It must be call when both stream and video capture are not running. * * Use [IConfigurationInfo] to get value limits. @@ -318,7 +354,7 @@ abstract class BaseStreamer( /** * Configures both video and audio settings. - * It is the first method to call after a [BaseStreamer] instantiation. + * It is the first method to call after a [DefaultStreamer] instantiation. * It must be call when both stream and audio and video capture are not running. * * Use [IConfigurationInfo] to get value limits. @@ -337,6 +373,22 @@ abstract class BaseStreamer( configure(videoConfig) } + /** + * Opens the streamer endpoint. + * + * @param descriptor Media descriptor to open + */ + override suspend fun open(descriptor: MediaDescriptor) = withContext(dispatcher) { + internalEndpoint.open(descriptor) + } + + /** + * Closes the streamer endpoint. + */ + override suspend fun close() = withContext(dispatcher) { + internalEndpoint.close() + } + /** * Starts audio/video stream. * Stream depends of the endpoint: Audio/video could be write to a file or send to a remote @@ -345,7 +397,10 @@ abstract class BaseStreamer( * * @see [stopStream] */ - override suspend fun startStream() { + override suspend fun startStream() = withContext(dispatcher) { + require(isOpened.value) { "Endpoint must be opened before starting stream" } + require(!isStreaming.value) { "Stream is already running" } + try { val streams = mutableListOf() val orientedVideoConfig = if (hasVideo) { @@ -385,6 +440,7 @@ abstract class BaseStreamer( internalVideoSource?.startStream() codecSurface?.startStream() internalVideoEncoder?.startStream() + _isStreaming.emit(true) } catch (e: Exception) { stopStream() throw StreamPackError(e) @@ -399,12 +455,19 @@ abstract class BaseStreamer( * * @see [startStream] */ - override suspend fun stopStream() { + override suspend fun stopStream() = withContext(dispatcher) { + if (!isStreaming.value) { + Logger.w(TAG, "Stream is not running") + return@withContext + } + stopStreamImpl() // Encoder does not return to CONFIGURED state... so we have to reset everything... internalAudioEncoder?.reset() internalVideoEncoder?.reset() + + _isStreaming.emit(false) } /** @@ -413,12 +476,16 @@ abstract class BaseStreamer( * @see [stopStream] */ private suspend fun stopStreamImpl() { + // Sources + internalAudioSource?.stopStream() internalVideoSource?.stopStream() codecSurface?.stopStream() - internalVideoEncoder?.stopStream() + + // Encoders internalAudioEncoder?.stopStream() - internalAudioSource?.stopStream() + internalVideoEncoder?.stopStream() + // Endpoint internalEndpoint.stopStream() } @@ -429,19 +496,22 @@ abstract class BaseStreamer( * @see [configure] */ override fun release() { + // Sources + internalAudioSource?.release() + internalVideoSource?.release() + codecSurface?.release() + + // Encoders internalAudioEncoder?.release() internalAudioEncoder = null - codecSurface?.release() internalVideoEncoder?.release() internalVideoEncoder = null - internalAudioSource?.release() - internalVideoSource?.release() - + // Endpoint internalEndpoint.release() } companion object { - private const val TAG = "BaseStreamer" + private const val TAG = "DefaultStreamer" } } \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyFlvFileStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyFlvFileStreamer.kt deleted file mode 100644 index 32de50726..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyFlvFileStreamer.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.file - -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.FlvMuxer -import java.io.File - -/** - * A [BaseAudioOnlyFileStreamer] that sends only microphone frames to a FLV [File]. - * - * @param context application context - */ -class AudioOnlyFlvFileStreamer( - context: Context, -) : BaseAudioOnlyFileStreamer( - context = context, - muxer = FlvMuxer(writeToFile = true) -) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyTsFileStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyTsFileStreamer.kt deleted file mode 100644 index a92a9e879..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/AudioOnlyTsFileStreamer.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.file - -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.utils.extensions.defaultTsServiceInfo -import java.io.File - -/** - * A [BaseAudioOnlyFileStreamer] that sends only microphone frames to a TS [File]. - * - * @param context application context - * @param tsServiceInfo MPEG-TS service description - */ -class AudioOnlyTsFileStreamer( - context: Context, - tsServiceInfo: TsServiceInfo = context.defaultTsServiceInfo -) : BaseAudioOnlyFileStreamer( - context = context, - muxer = TSMuxer().apply { addService(tsServiceInfo) } -) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/BaseAudioOnlyFileStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/BaseAudioOnlyFileStreamer.kt deleted file mode 100644 index 036a4b55e..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/BaseAudioOnlyFileStreamer.kt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.file - -import android.Manifest -import android.content.Context -import androidx.annotation.RequiresPermission -import io.github.thibaultbee.streampack.internal.endpoints.IFileEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.composites.FileCompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.sinks.FileSink -import io.github.thibaultbee.streampack.streamers.bases.BaseAudioOnlyStreamer -import io.github.thibaultbee.streampack.streamers.bases.BaseCameraStreamer -import io.github.thibaultbee.streampack.streamers.bases.BaseStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.IFileStreamer -import java.io.File -import java.io.FileDescriptor -import java.io.OutputStream - -/** - * A [BaseStreamer] that sends only microphone frames to a [File]. - * - * @param context application context - * @param muxer the [IMuxer] implementation - */ -open class BaseAudioOnlyFileStreamer( - context: Context, - muxer: IMuxer -) : BaseAudioOnlyStreamer( - context = context, - internalEndpoint = FileCompositeEndpoint(muxer, FileSink()) -), IFileStreamer { - private val fileEndpoint = internalEndpoint as IFileEndpoint - - /** - * Get/Set file. - * To set an [OutputStream] instead, see [outputStream]. - * - * @see [outputStream] - */ - override var file: File? - /** - * Get registered [File]. - * - * @return file where to write the stream - */ - get() = fileEndpoint.file - /** - * Set [File]. - * - * @param value [File] where to write the stream - */ - set(value) { - fileEndpoint.file = value - } - - /** - * Get/Set outputStream. - * To set an [File] instead, see [file]. - * - * @see file - */ - override var outputStream: OutputStream? - /** - * Get registered [OutputStream]. - * - * @return file where to write the stream - */ - get() = fileEndpoint.outputStream - /** - * Set [OutputStream]. - * - * @param value [OutputStream] to write the stream - */ - set(value) { - fileEndpoint.outputStream = value - } - - /** - * Get/Set fileDescriptor. - */ - override var fileDescriptor: FileDescriptor? - /** - * Get registered [FileDescriptor]. - */ - get() = fileEndpoint.fileDescriptor - /** - * Set [FileDescriptor]. - */ - set(value) { - fileEndpoint.fileDescriptor = value - } - - /** - * Same as [BaseCameraStreamer.startStream] with RequiresPermission annotation for - * Manifest.permission.WRITE_EXTERNAL_STORAGE. - */ - @RequiresPermission(allOf = [Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO]) - override suspend fun startStream() = super.startStream() -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/BaseCameraFileStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/BaseCameraFileStreamer.kt deleted file mode 100644 index 65b996d15..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/BaseCameraFileStreamer.kt +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.file - -import android.Manifest -import android.content.Context -import androidx.annotation.RequiresPermission -import io.github.thibaultbee.streampack.internal.endpoints.IFileEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.composites.FileCompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.sinks.FileSink -import io.github.thibaultbee.streampack.streamers.bases.BaseCameraStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.IFileStreamer -import java.io.File -import java.io.FileDescriptor -import java.io.OutputStream - -/** - * A [BaseCameraStreamer] that sends microphone and camera frames to a [File]. - * - * @param context application context - * @param muxer the [IMuxer] implementation - * @param enableAudio [Boolean.true] to capture audio. False to disable audio capture. - */ -open class BaseCameraFileStreamer( - context: Context, - enableAudio: Boolean = true, - muxer: IMuxer, -) : BaseCameraStreamer( - context = context, - enableAudio = enableAudio, - internalEndpoint = FileCompositeEndpoint(muxer, FileSink()) -), - IFileStreamer { - private val fileEndpoint = internalEndpoint as IFileEndpoint - - /** - * Get/Set file. - * To set an [OutputStream] instead, see [outputStream]. - * - * @see [outputStream] - */ - override var file: File? - /** - * Get registered [File]. - * - * @return file where to write the stream - */ - get() = fileEndpoint.file - /** - * Set [File]. - * - * @param value [File] where to write the stream - */ - set(value) { - fileEndpoint.file = value - } - - /** - * Get/Set outputStream. outputStream will be closed on [stopStream]. - * To set an [File] instead, see [file]. - * - * @see file - */ - override var outputStream: OutputStream? - /** - * Get registered [OutputStream]. - * - * @return file where to write the stream - */ - get() = fileEndpoint.outputStream - /** - * Set [OutputStream]. - * - * @param value [OutputStream] to write the stream - */ - set(value) { - fileEndpoint.outputStream = value - } - - /** - * Get/Set fileDescriptor. - */ - override var fileDescriptor: FileDescriptor? - /** - * Get registered [FileDescriptor]. - */ - get() = fileEndpoint.fileDescriptor - /** - * Set [FileDescriptor]. - */ - set(value) { - fileEndpoint.fileDescriptor = value - } - - /** - * Same as [BaseCameraStreamer.startStream] with RequiresPermission annotation for - * Manifest.permission.WRITE_EXTERNAL_STORAGE. - */ - @RequiresPermission(allOf = [Manifest.permission.WRITE_EXTERNAL_STORAGE]) - override suspend fun startStream() = super.startStream() -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraFlvFileStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraFlvFileStreamer.kt deleted file mode 100644 index acf9b3af3..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraFlvFileStreamer.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.file - -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.FlvMuxer -import java.io.File - -/** - * A [BaseCameraFileStreamer] that sends microphone and video frames to a FLV [File]. - * - * @param context application context - * @param enableAudio [Boolean.true] to capture audio. False to disable audio capture. - */ -class CameraFlvFileStreamer( - context: Context, - enableAudio: Boolean = true -) : BaseCameraFileStreamer( - context = context, - muxer = FlvMuxer(writeToFile = true), - enableAudio = enableAudio -) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraMp4FileStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraMp4FileStreamer.kt deleted file mode 100644 index 1f5c1ceb4..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraMp4FileStreamer.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.file - -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4Muxer -import java.io.File - -/** - * [BaseCameraFileStreamer] that sends microphone and video frames to a MP4 [File]. - * - * @param context application context - * @param enableAudio [Boolean.true] to capture audio. False to disable audio capture. - */ -class CameraMp4FileStreamer( - context: Context, - enableAudio: Boolean = true -) : BaseCameraFileStreamer( - context = context, - muxer = MP4Muxer(), - enableAudio = enableAudio -) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraTsFileStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraTsFileStreamer.kt deleted file mode 100644 index 3bd5df353..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/file/CameraTsFileStreamer.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.file - -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.utils.extensions.defaultTsServiceInfo -import java.io.File - -/** - * [BaseCameraFileStreamer] that sends microphone and video frames to a TS [File]. - * - * @param context application context - * @param enableAudio [Boolean.true] to capture audio. False to disable audio capture. - * @param tsServiceInfo MPEG-TS service description - */ -class CameraTsFileStreamer( - context: Context, - enableAudio: Boolean = true, - tsServiceInfo: TsServiceInfo = context.defaultTsServiceInfo -) : BaseCameraFileStreamer( - context = context, - muxer = TSMuxer().apply { addService(tsServiceInfo) }, - enableAudio = enableAudio -) \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/helpers/CameraStreamerConfigurationInfo.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/helpers/CameraStreamerConfigurationInfo.kt index 737421c77..cb8d52fd2 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/helpers/CameraStreamerConfigurationInfo.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/helpers/CameraStreamerConfigurationInfo.kt @@ -20,17 +20,17 @@ import android.util.Range import android.util.Size import io.github.thibaultbee.streampack.internal.endpoints.composites.CompositeEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IPublicEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.FlvMuxerInfo -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4MuxerInfo -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSMuxerInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.FlvMuxerInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4MuxerInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSMuxerInfo import io.github.thibaultbee.streampack.internal.utils.av.video.DynamicRangeProfile -import io.github.thibaultbee.streampack.streamers.bases.BaseCameraStreamer +import io.github.thibaultbee.streampack.streamers.DefaultCameraStreamer import io.github.thibaultbee.streampack.utils.get10BitSupportedProfiles import io.github.thibaultbee.streampack.utils.getCameraFpsList import io.github.thibaultbee.streampack.utils.getCameraOutputStreamSizes /** - * Configuration infos\ for [BaseCameraStreamer]. + * Configuration infos\ for [DefaultCameraStreamer]. * It wraps supported values from MediaCodec, Camera and TS Muxer. */ class CameraStreamerConfigurationInfo(endpointInfo: IPublicEndpoint.IEndpointInfo) : @@ -70,7 +70,7 @@ class VideoCameraStreamerConfigurationInfo(videoEndpointInfo: IPublicEndpoint.IE } /** - * Get supported framerate for a [BaseCameraStreamer]. + * Get supported framerate for a [DefaultCameraStreamer]. * * @param context application context * @param mimeType video encoder mime type @@ -87,7 +87,7 @@ class VideoCameraStreamerConfigurationInfo(videoEndpointInfo: IPublicEndpoint.IE } /** - * Get supported 8-bit and 10-bit profiles for a [BaseCameraStreamer]. + * Get supported 8-bit and 10-bit profiles for a [DefaultCameraStreamer]. * * @param context application context * @param mimeType video encoder mime type diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/helpers/StreamerConfigurationInfo.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/helpers/StreamerConfigurationInfo.kt index 609b84690..a7793e2e7 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/helpers/StreamerConfigurationInfo.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/helpers/StreamerConfigurationInfo.kt @@ -42,15 +42,15 @@ import android.util.Range import io.github.thibaultbee.streampack.internal.encoders.mediacodec.MediaCodecHelper import io.github.thibaultbee.streampack.internal.endpoints.composites.CompositeEndpoint import io.github.thibaultbee.streampack.internal.endpoints.IPublicEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.FlvMuxerInfo -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4MuxerInfo -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSMuxerInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.FlvMuxerInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4MuxerInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSMuxerInfo import io.github.thibaultbee.streampack.internal.utils.av.video.DynamicRangeProfile -import io.github.thibaultbee.streampack.streamers.bases.BaseStreamer +import io.github.thibaultbee.streampack.streamers.DefaultStreamer import java.security.InvalidParameterException /** - * Configuration info for [BaseStreamer]. + * Configuration info for [DefaultStreamer]. * It wraps supported values from MediaCodec and TS Muxer. * * @param endpointInfo the corresponding muxer info @@ -82,7 +82,7 @@ class AudioStreamerConfigurationInfo(private val audioEndpointInfo: IPublicEndpo } /** - * Get supported bitrate range for a [BaseStreamer]. + * Get supported bitrate range for a [DefaultStreamer]. * * @param mimeType audio encoder mime type * @return bitrate range @@ -136,7 +136,7 @@ class AudioStreamerConfigurationInfo(private val audioEndpointInfo: IPublicEndpo } /** - * Get supported profiles for a [BaseStreamer]. + * Get supported profiles for a [DefaultStreamer]. * * @param mimeType video encoder mime type * @return list of profile @@ -149,14 +149,14 @@ class AudioStreamerConfigurationInfo(private val audioEndpointInfo: IPublicEndpo open class VideoStreamerConfigurationInfo(private val videoEndpointInfo: IPublicEndpoint.IEndpointInfo.IVideoEndpointInfo) : IVideoConfigurationInfo { /** - * Supported encoders for a [BaseStreamer] + * Supported encoders for a [DefaultStreamer] */ override val supportedEncoders = MediaCodecHelper.Video.supportedEncoders.filter { videoEndpointInfo.supportedEncoders.contains(it) } /** - * Get supported bitrate range for a [BaseStreamer]. + * Get supported bitrate range for a [DefaultStreamer]. * * @param mimeType video encoder mime type * @return bitrate range @@ -178,7 +178,7 @@ open class VideoStreamerConfigurationInfo(private val videoEndpointInfo: IPublic } /** - * Get supported framerate for a [BaseStreamer]. + * Get supported framerate for a [DefaultStreamer]. * * @param mimeType video encoder mime type * @return framerate range supported by encoder @@ -188,7 +188,7 @@ open class VideoStreamerConfigurationInfo(private val videoEndpointInfo: IPublic ) = MediaCodecHelper.Video.getFramerateRange(mimeType) /** - * Get supported 8-bit and 10-bit profiles for a [BaseStreamer]. + * Get supported 8-bit and 10-bit profiles for a [DefaultStreamer]. * Removes profiles for 10 bits and still images. * * @param mimeType video encoder mime type @@ -222,7 +222,7 @@ open class VideoStreamerConfigurationInfo(private val videoEndpointInfo: IPublic } /** - * Get supported HDR (10-bit only) profiles for a [BaseStreamer]. + * Get supported HDR (10-bit only) profiles for a [DefaultStreamer]. * Removes profiles for 8 bits and still images. * * @param mimeType video encoder mime type @@ -239,7 +239,7 @@ open class VideoStreamerConfigurationInfo(private val videoEndpointInfo: IPublic } /** - * Get supported SDR (8-bit only) profiles for a [BaseStreamer]. + * Get supported SDR (8-bit only) profiles for a [DefaultStreamer]. * Removes profiles for 10 bits and still images. * * @param mimeType video encoder mime type @@ -252,7 +252,7 @@ open class VideoStreamerConfigurationInfo(private val videoEndpointInfo: IPublic fun getSupportedProfiles(mimeType: String) = getSupportedSdrProfiles(mimeType) /** - * Get supported SDR (8-bit only) profiles for a [BaseStreamer]. + * Get supported SDR (8-bit only) profiles for a [DefaultStreamer]. * Removes profiles for 10 bits and still images. * * @param mimeType video encoder mime type diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICallbackStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICallbackStreamer.kt new file mode 100644 index 000000000..5ec8796a6 --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICallbackStreamer.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.streamers.interfaces + +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor + +interface ICallbackStreamer : IStreamer { + /** + * Returns true if endpoint is opened. + * For example, if the streamer is connected to a server if the endpoint is SRT or RTMP. + */ + val isOpened: Boolean + + /** + * Returns true if stream is running. + */ + val isStreaming: Boolean + + /** + * Opens the streamer endpoint asynchronously. + * + * @param descriptor Media descriptor to open + */ + fun open(descriptor: MediaDescriptor) + + /** + * Closes the streamer endpoint. + */ + fun close() + + /** + * Starts audio/video stream asynchronously. + * + * @see [stopStream] + */ + fun startStream() + + /** + * Starts audio/video stream asynchronously. + * + * Same as doing [open] and [startStream]. + * + * @see [stopStream] + */ + fun startStream(descriptor: MediaDescriptor) + + /** + * Stops audio/video stream asynchronously. + * + * @see [startStream] + */ + fun stopStream() +} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICameraStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICameraStreamer.kt index 635526ecf..be95bd1cd 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICameraStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICameraStreamer.kt @@ -22,7 +22,7 @@ import android.view.SurfaceView import android.view.TextureView import androidx.annotation.RequiresPermission import io.github.thibaultbee.streampack.internal.sources.video.camera.IPublicCameraSource -import io.github.thibaultbee.streampack.streamers.bases.BaseStreamer +import io.github.thibaultbee.streampack.streamers.DefaultStreamer interface ICameraStreamer { /** @@ -38,7 +38,7 @@ interface ICameraStreamer { /** * Starts audio and video capture. - * [BaseStreamer.configure] must have been called at least once. + * [DefaultStreamer.configure] must have been called at least once. * * @param previewSurface The [Surface] used for camera preview * @param cameraId The camera id where to start preview @@ -50,7 +50,7 @@ interface ICameraStreamer { /** * Starts audio and video capture. - * [BaseStreamer.configure] must have been called at least once. + * [DefaultStreamer.configure] must have been called at least once. * * @param surfaceView The [SurfaceView] used for camera preview * @param cameraId The camera id where to start preview @@ -63,7 +63,7 @@ interface ICameraStreamer { /** * Starts audio and video capture. - * [BaseStreamer.configure] must have been called at least once. + * [DefaultStreamer.configure] must have been called at least once. * * @param surfaceHolder The [SurfaceHolder] used for camera preview * @param cameraId The camera id where to start preview @@ -76,7 +76,7 @@ interface ICameraStreamer { /** * Starts audio and video capture. - * [BaseStreamer.configure] must have been called at least once. + * [DefaultStreamer.configure] must have been called at least once. * * @param textureView The [TextureView] used for camera preview * @param cameraId The camera id where to start preview diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICoroutineStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICoroutineStreamer.kt new file mode 100644 index 000000000..4cd6f5c8b --- /dev/null +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ICoroutineStreamer.kt @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2021 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.streamers.interfaces + +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import kotlinx.coroutines.flow.StateFlow + +/** + * A Streamer based on coroutines. + */ +interface ICoroutineStreamer : IStreamer { + /** + * Returns the last exception that occurred. + */ + val exception: StateFlow + + /** + * Returns true if endpoint is opened. + * For example, if the streamer is connected to a server if the endpoint is SRT or RTMP. + */ + val isOpened: StateFlow + + /** + * Returns true if stream is running. + */ + val isStreaming: StateFlow + + /** + * Opens the streamer endpoint. + * + * @param descriptor Media descriptor to open + */ + suspend fun open(descriptor: MediaDescriptor) + + /** + * Closes the streamer endpoint. + */ + suspend fun close() + + /** + * Starts audio/video stream. + * + * @see [stopStream] + */ + suspend fun startStream() + + /** + * Starts audio/video stream. + * + * Same as doing [open] and [startStream]. + * + * @see [stopStream] + */ + suspend fun startStream(descriptor: MediaDescriptor) { + open(descriptor) + startStream() + } + + /** + * Stops audio/video stream. + * + * @see [startStream] + */ + suspend fun stopStream() +} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/IFileStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/IFileStreamer.kt deleted file mode 100644 index edccd9b8f..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/IFileStreamer.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.interfaces - -import java.io.File -import java.io.FileDescriptor -import java.io.OutputStream - -interface IFileStreamer { - /** - * [File] where o write the stream. - */ - var file: File? - - /** - * [OutputStream] where to write the stream. - */ - var outputStream: OutputStream? - - /** - * [FileDescriptor] where to write the stream. - */ - var fileDescriptor: FileDescriptor? -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ILiveStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ILiveStreamer.kt deleted file mode 100644 index e12d681b9..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/ILiveStreamer.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.interfaces - -import io.github.thibaultbee.streampack.listeners.OnConnectionListener - -interface ILiveStreamer { - /** - * Listen to manage connection events. - */ - var onConnectionListener: OnConnectionListener? - - /** - * Check if the streamer is connected to the server. - */ - val isConnected: Boolean - - /** - * Connect to a remote server. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param url server url - * @throws Exception if connection has failed or configuration has failed - */ - suspend fun connect(url: String) - - /** - * Disconnect from the remote server. - * - * @throws Exception is not connected - */ - fun disconnect() - - /** - * Connect to a RTMP server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param url server url (syntax: rtmp://server/streamKey) - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - suspend fun startStream(url: String) -} diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/IStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/IStreamer.kt index 79f71af1f..d23e0cf43 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/IStreamer.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/interfaces/IStreamer.kt @@ -22,23 +22,15 @@ import io.github.thibaultbee.streampack.data.VideoConfig import io.github.thibaultbee.streampack.error.StreamPackError import io.github.thibaultbee.streampack.internal.encoders.IPublicEncoder import io.github.thibaultbee.streampack.internal.endpoints.IPublicEndpoint +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor import io.github.thibaultbee.streampack.internal.sources.audio.IPublicAudioSource import io.github.thibaultbee.streampack.internal.sources.video.IPublicVideoSource -import io.github.thibaultbee.streampack.listeners.OnErrorListener import io.github.thibaultbee.streampack.streamers.helpers.IConfigurationInfo +/** + * A Streamer that is agnostic to the underlying implementation (either with coroutines or callbacks). + */ interface IStreamer { - /** - * Listener that reports streamer error. - * Supports only one listener. - */ - var onErrorListener: OnErrorListener? - - /** - * Access configuration info. - */ - val info: IConfigurationInfo - /** * Advanced settings for the audio source. */ @@ -64,6 +56,16 @@ interface IStreamer { */ val endpoint: IPublicEndpoint + /** + * Configuration information + */ + val info: IConfigurationInfo + + /** + * Gets configuration information + */ + fun getInfo(descriptor: MediaDescriptor): IConfigurationInfo + /** * Configures only audio settings. * @@ -97,22 +99,6 @@ interface IStreamer { @RequiresPermission(Manifest.permission.RECORD_AUDIO) fun configure(audioConfig: AudioConfig, videoConfig: VideoConfig) - /** - * Starts audio/video stream. - * - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @see [stopStream] - */ - suspend fun startStream() - - /** - * Stops audio/video stream. - * - * @see [startStream] - */ - suspend fun stopStream() - /** * Clean and reset the streamer. * diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseAudioOnlyLiveStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseAudioOnlyLiveStreamer.kt deleted file mode 100644 index 225201b4e..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseAudioOnlyLiveStreamer.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.live - -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.IConnectableEndpoint -import io.github.thibaultbee.streampack.listeners.OnConnectionListener -import io.github.thibaultbee.streampack.streamers.bases.BaseAudioOnlyStreamer -import io.github.thibaultbee.streampack.streamers.bases.BaseStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.ILiveStreamer - -/** - * A [BaseStreamer] that sends only microphone frames to a remote device. - * - * @param context application context - * @param internalEndpoint the [IConnectableEndpoint] implementation - */ -open class BaseAudioOnlyLiveStreamer( - context: Context, - internalEndpoint: IConnectableEndpoint, -) : BaseAudioOnlyStreamer( - context = context, - internalEndpoint = internalEndpoint, -), ILiveStreamer { - private val liveProducer = internalEndpoint - - /** - * Listener to manage connection. - */ - override var onConnectionListener: OnConnectionListener? = null - set(value) { - liveProducer.onConnectionListener = value - field = value - } - - /** - * Check if the streamer is connected to the server. - */ - override val isConnected: Boolean - get() = liveProducer.isConnected - - /** - * Connect to an remove server. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param url server url - * @throws Exception if connection has failed or configuration has failed - */ - override suspend fun connect(url: String) { - liveProducer.connect(url) - } - - /** - * Disconnect from the remote server. - * - * @throws Exception is not connected - */ - override fun disconnect() { - liveProducer.disconnect() - } - - /** - * Connect to a remote server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param url server url (syntax: rtmp://server/app/streamKey or srt://ip:port) - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - override suspend fun startStream(url: String) { - connect(url) - try { - startStream() - } catch (e: Exception) { - disconnect() - throw e - } - } -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseCameraLiveStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseCameraLiveStreamer.kt deleted file mode 100644 index 87f2311a4..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseCameraLiveStreamer.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.live - -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.IConnectableEndpoint -import io.github.thibaultbee.streampack.listeners.OnConnectionListener -import io.github.thibaultbee.streampack.streamers.bases.BaseCameraStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.ILiveStreamer - -/** - * A [BaseCameraStreamer] that sends microphone and camera frames to a remote device. - * - * @param context application context - * @param enableAudio [Boolean.true] to capture audio. False to disable audio capture. - * @param internalEndpoint the [IConnectableEndpoint] implementation - */ -open class BaseCameraLiveStreamer( - context: Context, - enableAudio: Boolean = true, - internalEndpoint: IConnectableEndpoint -) : BaseCameraStreamer( - context = context, - enableAudio = enableAudio, - internalEndpoint = internalEndpoint, -), - ILiveStreamer { - private val liveEndpoint = internalEndpoint - - /** - * Listener to manage connection. - */ - override var onConnectionListener: OnConnectionListener? = null - set(value) { - liveEndpoint.onConnectionListener = value - field = value - } - - /** - * Check if the streamer is connected to the server. - */ - override val isConnected: Boolean - get() = liveEndpoint.isConnected - - /** - * Connect to an remove server. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param url server url - * @throws Exception if connection has failed or configuration has failed - */ - override suspend fun connect(url: String) { - liveEndpoint.connect(url) - } - - /** - * Disconnect from the remote server. - * - * @throws Exception is not connected - */ - override fun disconnect() { - liveEndpoint.disconnect() - } - - /** - * Connect to a remote server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param url server url (syntax: rtmp://server/app/streamKey or srt://ip:port) - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - override suspend fun startStream(url: String) { - connect(url) - try { - startStream() - } catch (e: Exception) { - disconnect() - throw e - } - } -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseScreenRecorderLiveStreamer.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseScreenRecorderLiveStreamer.kt deleted file mode 100644 index dfbed54c7..000000000 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/live/BaseScreenRecorderLiveStreamer.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.streamers.live - -import android.content.Context -import io.github.thibaultbee.streampack.internal.endpoints.IConnectableEndpoint -import io.github.thibaultbee.streampack.listeners.OnConnectionListener -import io.github.thibaultbee.streampack.streamers.bases.BaseScreenRecorderStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.ILiveStreamer - -/** - * A [BaseScreenRecorderStreamer] that sends microphone and screen frames to a remote device. - * - * @param context application context - * @param enableAudio [Boolean.true] to capture audio. False to disable audio capture. - * @param internalEndpoint the [IConnectableEndpoint] implementation - */ -open class BaseScreenRecorderLiveStreamer( - context: Context, - enableAudio: Boolean = true, - internalEndpoint: IConnectableEndpoint -) : BaseScreenRecorderStreamer( - context = context, - enableAudio = enableAudio, - internalEndpoint = internalEndpoint -), - ILiveStreamer { - private val liveProducer = internalEndpoint - - /** - * Listener to manage connection. - */ - override var onConnectionListener: OnConnectionListener? = null - set(value) { - liveProducer.onConnectionListener = value - field = value - } - - /** - * Check if the streamer is connected to the server. - */ - override val isConnected: Boolean - get() = liveProducer.isConnected - - /** - * Connect to an remove server. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param url server url - * @throws Exception if connection has failed or configuration has failed - */ - override suspend fun connect(url: String) { - liveProducer.connect(url) - } - - /** - * Disconnect from the remote server. - * - * @throws Exception is not connected - */ - override fun disconnect() { - liveProducer.disconnect() - } - - /** - * Connect to a remote server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param url server url (syntax: rtmp://server/app/streamKey or srt://ip:port) - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - override suspend fun startStream(url: String) { - connect(url) - try { - startStream() - } catch (e: Exception) { - disconnect() - throw e - } - } -} \ No newline at end of file diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/StreamerLifeCycleObserver.kt b/core/src/main/java/io/github/thibaultbee/streampack/streamers/observers/StreamerLifeCycleObserver.kt similarity index 69% rename from core/src/main/java/io/github/thibaultbee/streampack/streamers/StreamerLifeCycleObserver.kt rename to core/src/main/java/io/github/thibaultbee/streampack/streamers/observers/StreamerLifeCycleObserver.kt index 9c435be1f..fd999167a 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/StreamerLifeCycleObserver.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/streamers/observers/StreamerLifeCycleObserver.kt @@ -13,35 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.streamers +package io.github.thibaultbee.streampack.streamers.observers import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner -import io.github.thibaultbee.streampack.streamers.interfaces.IStreamer +import io.github.thibaultbee.streampack.streamers.interfaces.ICoroutineStreamer import io.github.thibaultbee.streampack.utils.getCameraStreamer -import io.github.thibaultbee.streampack.utils.getLiveStreamer import kotlinx.coroutines.runBlocking /** * Add [DefaultLifecycleObserver] to a streamer. * - * You will not have to call [IStreamer.release] when application is destroyed nor to to call - * [IStreamer.stopStream] when application goes to background. + * You will not have to call [ICoroutineStreamer.release] when application is destroyed nor to to call + * [ICoroutineStreamer.stopStream] when application goes to background. * * To use it, call: * - `lifeCycle.addObserver(StreamerLifeCycleObserver(streamer))` * * @param streamer The streamer to observe */ -open class StreamerLifeCycleObserver(var streamer: IStreamer) : DefaultLifecycleObserver { +open class StreamerLifeCycleObserver(var streamer: ICoroutineStreamer) : DefaultLifecycleObserver { override fun onPause(owner: LifecycleOwner) { streamer.getCameraStreamer()?.stopPreview() runBlocking { streamer.stopStream() - } - streamer.getLiveStreamer()?.let { - if (it.isConnected) { - it.disconnect() + if (streamer.endpoint.isOpened.value) { + streamer.close() } } } diff --git a/core/src/main/java/io/github/thibaultbee/streampack/utils/ChunkedFileOutputStream.kt b/core/src/main/java/io/github/thibaultbee/streampack/utils/ChunkedFileOutputStream.kt index 5d6ea5766..32079c1b4 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/utils/ChunkedFileOutputStream.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/utils/ChunkedFileOutputStream.kt @@ -15,7 +15,6 @@ */ package io.github.thibaultbee.streampack.utils -import io.github.thibaultbee.streampack.streamers.interfaces.IFileStreamer import java.io.File import java.io.FileOutputStream import java.io.OutputStream diff --git a/core/src/main/java/io/github/thibaultbee/streampack/utils/StreamerExtensions.kt b/core/src/main/java/io/github/thibaultbee/streampack/utils/StreamerExtensions.kt index 0b8b09da0..0ddd12209 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/utils/StreamerExtensions.kt +++ b/core/src/main/java/io/github/thibaultbee/streampack/utils/StreamerExtensions.kt @@ -17,14 +17,12 @@ package io.github.thibaultbee.streampack.utils import io.github.thibaultbee.streampack.streamers.interfaces.ICameraStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.IFileStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.ILiveStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.IStreamer +import io.github.thibaultbee.streampack.streamers.interfaces.ICoroutineStreamer /** * Get a streamer if it from generic class or interface */ -inline fun IStreamer.getStreamer(): T? { +inline fun ICoroutineStreamer.getStreamer(): T? { return if (this is T) { this } else { @@ -32,8 +30,4 @@ inline fun IStreamer.getStreamer(): T? { } } -fun IStreamer.getCameraStreamer(): ICameraStreamer? = getStreamer() - -fun IStreamer.getLiveStreamer(): ILiveStreamer? = getStreamer() - -fun IStreamer.getFileStreamer() = getStreamer() +fun ICoroutineStreamer.getCameraStreamer(): ICameraStreamer? = getStreamer() \ No newline at end of file diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 19a42cb1a..ea06ba2ee 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -5,6 +5,4 @@ Connection lost Connection failed Live in progress… - StreamPack - Thibault B.s \ No newline at end of file diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/FileSinkTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/FileSinkTest.kt similarity index 70% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/FileSinkTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/FileSinkTest.kt index b822b3465..d3313789f 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/FileSinkTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/FileSinkTest.kt @@ -13,20 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints +package io.github.thibaultbee.streampack.internal.endpoints.composites +import androidx.core.net.toUri import io.github.thibaultbee.streampack.internal.data.Packet -import io.github.thibaultbee.streampack.internal.endpoints.sinks.FileSink +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.FileSink import io.github.thibaultbee.streampack.logger.Logger import io.github.thibaultbee.streampack.utils.FakeLogger import io.github.thibaultbee.streampack.utils.Utils -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Assert.* +import kotlinx.coroutines.test.runTest +import org.junit.Assert.assertArrayEquals +import org.junit.Assert.fail import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner import java.io.File import java.nio.ByteBuffer +@RunWith(RobolectricTestRunner::class) class FileSinkTest { private val filePublisher = FileSink() @@ -34,35 +40,27 @@ class FileSinkTest { Logger.logger = FakeLogger() } - @After - fun tearDown() { - filePublisher.release() - } - - private fun createTestFile(): File { - val tmpFile = File.createTempFile("test", ".tmp") + private fun createTestFile(suffix: String = ".tmp"): File { + val tmpFile = File.createTempFile("test", suffix) tmpFile.deleteOnExit() return tmpFile } @Test - fun `startStream with non existing file test`() { + fun `startStream with non existing file test`() = runTest { try { - runBlocking{ - filePublisher.startStream() - } + filePublisher.startStream() fail("Null file must not be streamable") } catch (_: Exception) { } } @Test - fun `write to non existing file test`() { + fun `write to non existing file test`() = runTest { + val randomArray = Utils.generateRandomArray(1024) + try { - val randomArray = Utils.generateRandomArray(1024) - runBlocking{ - filePublisher.startStream() - } + filePublisher.startStream() filePublisher.write( Packet( ByteBuffer.wrap(randomArray), @@ -75,15 +73,17 @@ class FileSinkTest { } @Test - fun `write buffer to file test`() { - val tmpFile = createTestFile() - - filePublisher.file = tmpFile + fun `write buffer to file test`() = runTest { + val tmpFile = createTestFile(".mp4") val randomArray = Utils.generateRandomArray(1024) + + filePublisher.open( + UriMediaDescriptor( + tmpFile.toUri() + ) + ) try { - runBlocking{ - filePublisher.startStream() - } + filePublisher.startStream() filePublisher.write( Packet( ByteBuffer.wrap(randomArray), @@ -91,23 +91,21 @@ class FileSinkTest { ) ) assertArrayEquals(randomArray, tmpFile.readBytes()) - runBlocking { - filePublisher.stopStream() - } + filePublisher.stopStream() } catch (e: Exception) { - fail() + fail("Failed to write buffer to file: ${e.message}") } - filePublisher.release() } + /* TODO @Test - fun `write buffer to outputStream test`() { + fun `write buffer to outputStream test`() = runTest{ val tmpFile = createTestFile() filePublisher.outputStream = tmpFile.outputStream() val randomArray = Utils.generateRandomArray(1024) try { - runBlocking{ + runBlocking { filePublisher.startStream() } filePublisher.write( @@ -153,5 +151,5 @@ class FileSinkTest { fail() } filePublisher.release() - } + }*/ } \ No newline at end of file diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfEcmaArrayTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfEcmaArrayTest.kt similarity index 76% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfEcmaArrayTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfEcmaArrayTest.kt index 12fe7ded0..81979e080 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/containers/AmfEcmaArrayTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/containers/AmfEcmaArrayTest.kt @@ -1,6 +1,6 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.containers +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.containers -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfBooleanTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfBooleanTest.kt similarity index 75% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfBooleanTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfBooleanTest.kt index f7604856e..c14d0b97d 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfBooleanTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfBooleanTest.kt @@ -1,6 +1,6 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt32Test.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt32Test.kt similarity index 55% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt32Test.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt32Test.kt index ad6ecee63..94c30c91e 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfInt32Test.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfInt32Test.kt @@ -1,6 +1,6 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives.AmfInt32 +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives.AmfInt32 import org.junit.Assert.* import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNamedParameterTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNamedParameterTest.kt similarity index 90% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNamedParameterTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNamedParameterTest.kt index 3660eb7f5..134d80050 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfNamedParameterTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfNamedParameterTest.kt @@ -1,4 +1,4 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.* diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfStringTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfStringTest.kt similarity index 73% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfStringTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfStringTest.kt index b5926a40b..cb1f8d6ff 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/amf/primitives/AmfStringTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/amf/primitives/AmfStringTest.kt @@ -1,6 +1,6 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.primitives +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.primitives -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.amf.AmfType +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.amf.AmfType import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/OnMetadataTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/OnMetadataTest.kt similarity index 98% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/OnMetadataTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/OnMetadataTest.kt index 0477135ec..54d02f22f 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/flv/tags/OnMetadataTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/flv/tags/OnMetadataTest.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.tags import android.media.MediaCodecInfo import android.util.Size diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4ResourcesUtils.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4ResourcesUtils.kt similarity index 92% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4ResourcesUtils.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4ResourcesUtils.kt index 0a5c4be77..a8834bb4f 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/MP4ResourcesUtils.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/MP4ResourcesUtils.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4 +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4 import io.github.thibaultbee.streampack.utils.ResourcesUtils import java.nio.ByteBuffer diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCConfigurationBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCConfigurationBoxTest.kt similarity index 92% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCConfigurationBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCConfigurationBoxTest.kt index c30e90752..f7b82c0d0 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCConfigurationBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCConfigurationBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.av.video.avc.AVCDecoderConfigurationRecord import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCSampleEntryTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCSampleEntryTest.kt similarity index 93% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCSampleEntryTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCSampleEntryTest.kt index c44eb2dd9..e9b129aea 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/AVCSampleEntryTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/AVCSampleEntryTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.av.video.avc.AVCDecoderConfigurationRecord import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import io.github.thibaultbee.streampack.utils.MockUtils diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/BitRateBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/BitRateBoxTest.kt similarity index 85% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/BitRateBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/BitRateBoxTest.kt index c364ec7c1..27e438157 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/BitRateBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/BitRateBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ChunkOffsetBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ChunkOffsetBoxTest.kt similarity index 85% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ChunkOffsetBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ChunkOffsetBoxTest.kt index 7de88c5b8..3bae56056 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/ChunkOffsetBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/ChunkOffsetBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataInformationBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataInformationBoxTest.kt similarity index 85% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataInformationBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataInformationBoxTest.kt index 6d4454347..01e5fd0d1 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataInformationBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataInformationBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataReferenceBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataReferenceBoxTest.kt similarity index 87% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataReferenceBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataReferenceBoxTest.kt index 68185f394..28bdfa409 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/DataReferenceBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/DataReferenceBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Assert.fail diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/FileTypeBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/FileTypeBoxTest.kt similarity index 89% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/FileTypeBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/FileTypeBoxTest.kt index 3f99cd08c..684a5c304 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/FileTypeBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/FileTypeBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Assert.fail diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCConfigurationBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCConfigurationBoxTest.kt similarity index 96% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCConfigurationBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCConfigurationBoxTest.kt index b2c8300a9..e77d9b387 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCConfigurationBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCConfigurationBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.av.video.ChromaFormat import io.github.thibaultbee.streampack.internal.utils.av.video.hevc.HEVCDecoderConfigurationRecord import io.github.thibaultbee.streampack.internal.utils.av.video.hevc.HEVCProfile diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCSampleEntryTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCSampleEntryTest.kt similarity index 95% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCSampleEntryTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCSampleEntryTest.kt index 49e2c2a2c..6dca1673c 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HEVCSampleEntryTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HEVCSampleEntryTest.kt @@ -1,6 +1,6 @@ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.av.video.ChromaFormat import io.github.thibaultbee.streampack.internal.utils.av.video.hevc.HEVCDecoderConfigurationRecord import io.github.thibaultbee.streampack.internal.utils.av.video.hevc.HEVCProfile diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HandlerBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HandlerBoxTest.kt similarity index 85% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HandlerBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HandlerBoxTest.kt index a21bef371..3cee1db88 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/HandlerBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/HandlerBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MP4AudioSampleEntryTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MP4AudioSampleEntryTest.kt similarity index 93% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MP4AudioSampleEntryTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MP4AudioSampleEntryTest.kt index 51bee0041..e71d6969d 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MP4AudioSampleEntryTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MP4AudioSampleEntryTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.av.descriptors.DecoderConfigDescriptor import io.github.thibaultbee.streampack.internal.utils.av.descriptors.DecoderSpecificInfo import io.github.thibaultbee.streampack.internal.utils.av.descriptors.ESDescriptor diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentHeaderBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentHeaderBoxTest.kt similarity index 85% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentHeaderBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentHeaderBoxTest.kt index 2ff66a3c9..60b4dc527 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentHeaderBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentHeaderBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessBoxTest.kt similarity index 95% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessBoxTest.kt index 4a7a4630e..346bfd085 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieFragmentRandomAccessBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieFragmentRandomAccessBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieHeaderBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieHeaderBoxTest.kt similarity index 87% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieHeaderBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieHeaderBoxTest.kt index 859ec479b..a06515805 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/MovieHeaderBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/MovieHeaderBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/OpusSampleEntryTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/OpusSampleEntryTest.kt similarity index 88% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/OpusSampleEntryTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/OpusSampleEntryTest.kt index 419889c64..b3bf39bb3 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/OpusSampleEntryTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/OpusSampleEntryTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleSizeBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleSizeBoxTest.kt similarity index 99% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleSizeBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleSizeBoxTest.kt index 08ec6a3fa..1ec6ca6fb 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleSizeBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleSizeBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleToChunkBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleToChunkBoxTest.kt similarity index 86% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleToChunkBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleToChunkBoxTest.kt index ba267d7b5..e77e3e908 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SampleToChunkBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SampleToChunkBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SoundMediaHeaderBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SoundMediaHeaderBoxTest.kt similarity index 84% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SoundMediaHeaderBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SoundMediaHeaderBoxTest.kt index 9fd78e0f7..1c8a035a8 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SoundMediaHeaderBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SoundMediaHeaderBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SyncSampleBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SyncSampleBoxTest.kt similarity index 91% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SyncSampleBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SyncSampleBoxTest.kt index 97e8be146..c01c1972a 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/SyncSampleBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/SyncSampleBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TimeToSampleBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TimeToSampleBoxTest.kt similarity index 89% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TimeToSampleBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TimeToSampleBoxTest.kt index 84fc855ec..63ad9ad1e 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TimeToSampleBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TimeToSampleBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBoxTest.kt similarity index 85% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBoxTest.kt index e401d6d39..8e209f5c5 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentBaseMediaDecodeTimeBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentHeaderBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentHeaderBoxTest.kt similarity index 78% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentHeaderBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentHeaderBoxTest.kt index 225c8d6a1..3ed321e93 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentHeaderBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentHeaderBoxTest.kt @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.SampleDependsOn -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.SampleFlags +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.SampleDependsOn +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.SampleFlags import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentRandomAccessBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentRandomAccessBoxTest.kt similarity index 92% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentRandomAccessBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentRandomAccessBoxTest.kt index 7581fd80e..873ad4a57 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackFragmentRandomAccessBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackFragmentRandomAccessBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackHeaderBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackHeaderBoxTest.kt similarity index 88% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackHeaderBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackHeaderBoxTest.kt index da6291aef..7ea3fe1d2 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackHeaderBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackHeaderBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import io.github.thibaultbee.streampack.utils.MockUtils import org.junit.Assert.assertArrayEquals diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackRunBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackRunBoxTest.kt similarity index 87% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackRunBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackRunBoxTest.kt index a72f43142..67f67ed87 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/TrackRunBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/TrackRunBoxTest.kt @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.SampleDependsOn -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.models.SampleFlags +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.SampleDependsOn +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.models.SampleFlags import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/VideoMediaHeaderBoxTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/VideoMediaHeaderBoxTest.kt similarity index 84% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/VideoMediaHeaderBoxTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/VideoMediaHeaderBoxTest.kt index 243f938ef..e56d9da9f 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/mp4/boxes/VideoMediaHeaderBoxTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/mp4/boxes/VideoMediaHeaderBoxTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.boxes +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.boxes -import io.github.thibaultbee.streampack.internal.endpoints.muxers.mp4.MP4ResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.mp4.MP4ResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxerTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxerTest.kt similarity index 69% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxerTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxerTest.kt index 2975e8f2c..d1f67ebac 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSMuxerTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSMuxerTest.kt @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts import android.media.MediaCodecInfo import android.media.MediaFormat import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.VideoConfig import io.github.thibaultbee.streampack.internal.data.Packet -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.TSConst -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.Utils.createFakeServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.TSConst +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.Utils.createFakeServiceInfo import io.github.thibaultbee.streampack.utils.FakeFrames import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -32,12 +32,12 @@ import org.junit.Test class TSMuxerTest { class MockMuxerListener : - IMuxer.IMuxerListener { + io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener { override fun onOutputFrame(packet: Packet) {} } @Test - fun `add streams in constructor test`() { + fun `add streams test`() { val vStreamConfig1 = VideoConfig( mimeType = MediaFormat.MIMETYPE_VIDEO_AVC, @@ -51,12 +51,16 @@ class TSMuxerTest { level = MediaCodecInfo.CodecProfileLevel.AVCLevel31 ) val aStreamConfig = AudioConfig(mimeType = MediaFormat.MIMETYPE_AUDIO_AAC) + val service = createFakeServiceInfo() + val tsMux = - TSMuxer( - MockMuxerListener(), - createFakeServiceInfo(), - listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) - ) + TSMuxer().apply { + addService(service) + addStreams( + service, + listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) + ) + } assertEquals(TSConst.BASE_PID, tsMux.getStreams(vStreamConfig1.mimeType)[0].pid) assertEquals( (TSConst.BASE_PID + 1).toShort(), @@ -68,32 +72,6 @@ class TSMuxerTest { ) } - @Test - fun `add streams test`() { - val vStreamConfig1 = - VideoConfig( - mimeType = MediaFormat.MIMETYPE_VIDEO_AVC, - profile = MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline, - level = MediaCodecInfo.CodecProfileLevel.AVCLevel31 - ) - val vStreamConfig2 = - VideoConfig( - mimeType = MediaFormat.MIMETYPE_VIDEO_HEVC, - profile = MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline, - level = MediaCodecInfo.CodecProfileLevel.AVCLevel31 - ) - val aStreamConfig = AudioConfig(mimeType = MediaFormat.MIMETYPE_AUDIO_AAC) - val tsMux = TSMuxer(MockMuxerListener(), createFakeServiceInfo()) - tsMux.addStreams( - createFakeServiceInfo(), - listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) - ).run { - assertEquals(TSConst.BASE_PID.toInt(), this[vStreamConfig1]) - assertEquals((TSConst.BASE_PID + 1), this[vStreamConfig2]) - assertEquals((TSConst.BASE_PID + 2), this[aStreamConfig]) - } - } - @Test fun `constructor with streams and no service test`() { val vStreamConfig1 = @@ -110,10 +88,11 @@ class TSMuxerTest { ) val aStreamConfig = AudioConfig(mimeType = MediaFormat.MIMETYPE_AUDIO_AAC) try { - TSMuxer( - MockMuxerListener(), - initialStreams = listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) - ) + TSMuxer().apply { + addStreams( + listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) + ) + } fail() } catch (_: Exception) { } @@ -122,7 +101,9 @@ class TSMuxerTest { @Test fun `re-add existing service test`() { val service = createFakeServiceInfo() - val tsMux = TSMuxer(MockMuxerListener(), service) + val tsMux = TSMuxer().apply { + addService(service) + } try { tsMux.addService(service) fail() @@ -145,23 +126,27 @@ class TSMuxerTest { level = MediaCodecInfo.CodecProfileLevel.AVCLevel31 ) val aStreamConfig = AudioConfig(mimeType = MediaFormat.MIMETYPE_AUDIO_AAC) - val tsMux = - TSMuxer( - MockMuxerListener(), - createFakeServiceInfo(), - listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) - ) - assertTrue(tsMux.getServices().contains(createFakeServiceInfo())) + val service = createFakeServiceInfo() - tsMux.removeService(createFakeServiceInfo()) - assertFalse(tsMux.getServices().contains(createFakeServiceInfo())) + val tsMux = + TSMuxer().apply { + addService(service) + addStreams( + service, + listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) + ) + } + assertTrue(tsMux.getServices().contains(service)) + + tsMux.removeService(service) + assertFalse(tsMux.getServices().contains(service)) // Assert streams doe not exist assertTrue(tsMux.getStreams(vStreamConfig1.mimeType).isEmpty()) assertTrue(tsMux.getStreams(vStreamConfig2.mimeType).isEmpty()) assertTrue(tsMux.getStreams(aStreamConfig.mimeType).isEmpty()) try { // try to add a stream to this service - tsMux.addStreams(createFakeServiceInfo(), listOf(vStreamConfig1)) + tsMux.addStreams(service, listOf(vStreamConfig1)) fail() } catch (_: Exception) { } @@ -182,15 +167,19 @@ class TSMuxerTest { level = MediaCodecInfo.CodecProfileLevel.AVCLevel31 ) val aStreamConfig = AudioConfig(mimeType = MediaFormat.MIMETYPE_AUDIO_AAC) + val service = createFakeServiceInfo() + val tsMux = - TSMuxer( - MockMuxerListener(), - createFakeServiceInfo(), - listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) - ) + TSMuxer().apply { + addService(service) + addStreams( + service, + listOf(vStreamConfig1, vStreamConfig2, aStreamConfig) + ) + } tsMux.removeStreams( - createFakeServiceInfo(), + service, listOf(tsMux.getStreams(vStreamConfig1.mimeType)[0].pid) ) assertTrue(tsMux.getStreams(vStreamConfig1.mimeType).isEmpty()) @@ -199,7 +188,7 @@ class TSMuxerTest { @Test fun `encode without streams test`() { - val tsMux = TSMuxer(MockMuxerListener(), createFakeServiceInfo()) + val tsMux = TSMuxer() try { tsMux.write(FakeFrames.generate(mimeType = MediaFormat.MIMETYPE_VIDEO_AVC), -1) fail() @@ -209,7 +198,7 @@ class TSMuxerTest { @Test fun `encode with key frame with extra test `() { - val tsMux = TSMuxer(MockMuxerListener(), createFakeServiceInfo()) + val tsMux = TSMuxer() try { tsMux.write( FakeFrames.generate(mimeType = MediaFormat.MIMETYPE_VIDEO_AVC), -1 @@ -226,9 +215,13 @@ class TSMuxerTest { profile = MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline, level = MediaCodecInfo.CodecProfileLevel.AVCLevel31 ) - val tsMux = TSMuxer(MockMuxerListener(), createFakeServiceInfo()) + val service = createFakeServiceInfo() + + val tsMux = TSMuxer().apply { + addService(service) + } val streamPid = - tsMux.addStreams(createFakeServiceInfo(), listOf(config))[config]!! + tsMux.addStreams(service, listOf(config))[config]!! tsMux.write( FakeFrames.generate(mimeType = MediaFormat.MIMETYPE_VIDEO_AVC), streamPid @@ -242,7 +235,11 @@ class TSMuxerTest { @Test fun `encode aac frame test`() { val config = AudioConfig(mimeType = MediaFormat.MIMETYPE_AUDIO_AAC) - val tsMux = TSMuxer(MockMuxerListener(), createFakeServiceInfo()) + val service = createFakeServiceInfo() + + val tsMux = TSMuxer().apply { + addService(service) + } val streamPid = tsMux.addStreams(createFakeServiceInfo(), listOf(config))[config]!! diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSResourcesUtils.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSResourcesUtils.kt similarity index 92% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSResourcesUtils.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSResourcesUtils.kt index b4732d87c..6ad66e337 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/TSResourcesUtils.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/TSResourcesUtils.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts import io.github.thibaultbee.streampack.utils.ResourcesUtils import java.nio.ByteBuffer diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/descriptors/AdaptationFieldTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/descriptors/AdaptationFieldTest.kt similarity index 88% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/descriptors/AdaptationFieldTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/descriptors/AdaptationFieldTest.kt index 3b564f665..6e059034d 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/descriptors/AdaptationFieldTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/descriptors/AdaptationFieldTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.descriptors +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.descriptors -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSResourcesUtils import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert.assertArrayEquals import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/PesTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/PesTest.kt similarity index 93% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/PesTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/PesTest.kt index 793eb8460..3ab1d30f4 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/PesTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/PesTest.kt @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets import android.media.MediaCodecInfo import android.media.MediaFormat import io.github.thibaultbee.streampack.data.AudioConfig import io.github.thibaultbee.streampack.data.VideoConfig -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Stream -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.AssertEqualsBuffersMockMuxerListener +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Stream +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.AssertEqualsBuffersMockMuxerListener import io.github.thibaultbee.streampack.utils.FakeFrames import io.github.thibaultbee.streampack.utils.MockUtils import io.github.thibaultbee.streampack.utils.ResourcesUtils diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TransportStreamTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TransportStreamTest.kt similarity index 88% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TransportStreamTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TransportStreamTest.kt index 02d102f11..463463199 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/packets/TransportStreamTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/packets/TransportStreamTest.kt @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets import io.github.thibaultbee.streampack.internal.data.Packet -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.descriptors.AdaptationField +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.descriptors.AdaptationField import org.junit.Assert.assertEquals import org.junit.Test import java.nio.ByteBuffer @@ -28,7 +28,7 @@ class TransportStreamTest { class MockMuxerListener( private val expectedBuffer: ByteBuffer, private val numExpectedBuffer: Int = 1 - ) : IMuxer.IMuxerListener { + ) : io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener { private var nBuffer = 0 override fun onOutputFrame(packet: Packet) { assertEquals(TS.PACKET_SIZE * numExpectedBuffer, packet.buffer.limit()) @@ -45,7 +45,7 @@ class TransportStreamTest { } class MockTransportStream( - muxerListener: IMuxer.IMuxerListener, + muxerListener: io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener, pid: Short = Random.nextInt().toShort() ) : TS(muxerListener, pid) { diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PatTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PatTest.kt similarity index 64% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PatTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PatTest.kt index e3a463559..74b3ad833 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PatTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PatTest.kt @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.tables +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.tables -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSResourcesUtils -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Service -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Pat -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Pmt -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.AssertEqualsSingleBufferMockMuxerListener +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Service +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Pat +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Pmt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.AssertEqualsSingleBufferMockMuxerListener import org.junit.Test class PatTest { @@ -32,8 +32,8 @@ class PatTest { val expectedBuffer = TSResourcesUtils.readByteBuffer("pat.ts") val listener = AssertEqualsSingleBufferMockMuxerListener(expectedBuffer) val service = Service( - TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, // not used in this test + TSServiceInfo( + TSServiceInfo.ServiceType.DIGITAL_TV, // not used in this test id = 0x6d66, name = "ServiceName", // not used in this test providerName = "ProviderName" // not used in this test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PesHeaderTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PesHeaderTest.kt similarity index 84% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PesHeaderTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PesHeaderTest.kt index fde8c38e0..0529180ca 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PesHeaderTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PesHeaderTest.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.tables +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.tables -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSResourcesUtils -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.PesHeader +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.PesHeader import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert import org.junit.Test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PmtTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PmtTest.kt similarity index 67% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PmtTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PmtTest.kt index 4dcf9c1e7..03519d276 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/PmtTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/PmtTest.kt @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.tables +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.tables import android.media.MediaFormat import io.github.thibaultbee.streampack.data.Config -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSResourcesUtils -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Service -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Stream -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Pmt -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.AssertEqualsSingleBufferMockMuxerListener +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Service +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Stream +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Pmt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.AssertEqualsSingleBufferMockMuxerListener import org.junit.Test class PmtTest { @@ -35,8 +35,8 @@ class PmtTest { val listener = AssertEqualsSingleBufferMockMuxerListener(expectedBuffer) val service = Service( - TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, // not used in this test + TSServiceInfo( + TSServiceInfo.ServiceType.DIGITAL_TV, // not used in this test id = 0x0001, name = "ServiceName", // not used in this test providerName = "ProviderName" // not used in this test diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/SdtTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/SdtTest.kt similarity index 64% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/SdtTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/SdtTest.kt index 87f9210ed..4c64a7bf1 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/SdtTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/SdtTest.kt @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.tables +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.tables -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSResourcesUtils -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.Service -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.Sdt -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils.AssertEqualsSingleBufferMockMuxerListener +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSResourcesUtils +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.Service +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.Sdt +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils.AssertEqualsSingleBufferMockMuxerListener import org.junit.Test class SdtTest { @@ -32,8 +32,8 @@ class SdtTest { val listener = AssertEqualsSingleBufferMockMuxerListener(expectedBuffer) val services = listOf( Service( - TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, + TSServiceInfo( + TSServiceInfo.ServiceType.DIGITAL_TV, id = 0x0001, name = "ServiceName", providerName = "ProviderName" diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/TableHeaderTest.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/TableHeaderTest.kt similarity index 88% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/TableHeaderTest.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/TableHeaderTest.kt index 177199ab3..9fe8c75c8 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/tables/TableHeaderTest.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/tables/TableHeaderTest.kt @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.tables +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.tables -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.TableHeader +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.TableHeader import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import io.github.thibaultbee.streampack.utils.ResourcesUtils import org.junit.Assert diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/MockUtils.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/MockUtils.kt similarity index 82% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/MockUtils.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/MockUtils.kt index 5cfc2bbdd..34ba63453 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/MockUtils.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/MockUtils.kt @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils import io.github.thibaultbee.streampack.internal.data.Packet -import io.github.thibaultbee.streampack.internal.endpoints.muxers.IMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.packets.TS +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.packets.TS import io.github.thibaultbee.streampack.internal.utils.extensions.toByteArray import org.junit.Assert import java.nio.ByteBuffer @@ -27,7 +27,7 @@ import java.nio.ByteBuffer * @param expectedBuffer expected buffer (pre-generated buffer) */ class AssertEqualsSingleBufferMockMuxerListener(private val expectedBuffer: ByteBuffer) : - IMuxer.IMuxerListener { + io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener { override fun onOutputFrame(packet: Packet) { Assert.assertEquals(expectedBuffer, packet.buffer) } @@ -38,7 +38,7 @@ class AssertEqualsSingleBufferMockMuxerListener(private val expectedBuffer: Byte * @param expectedBuffers expected buffers (often pre-generated buffers) */ class AssertEqualsBuffersMockMuxerListener(private val expectedBuffers: List) : - IMuxer.IMuxerListener { + io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.IMuxer.IMuxerListener { var expectedBufferIndex = 0 override fun onOutputFrame(packet: Packet) { diff --git a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/Utils.kt b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/Utils.kt similarity index 70% rename from core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/Utils.kt rename to core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/Utils.kt index e062e0bb8..2a3204ec0 100644 --- a/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/muxers/ts/utils/Utils.kt +++ b/core/src/test/java/io/github/thibaultbee/streampack/internal/endpoints/composites/muxers/ts/utils/Utils.kt @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.utils +package io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.utils -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo object Utils { - fun createFakeServiceInfo() = TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, + fun createFakeServiceInfo() = TSServiceInfo( + TSServiceInfo.ServiceType.DIGITAL_TV, 0x4698, "ServiceName", "ProviderName" diff --git a/core_settings.gradle b/core_settings.gradle index 9e39e5c1c..b6b2db051 100644 --- a/core_settings.gradle +++ b/core_settings.gradle @@ -2,6 +2,7 @@ rootProject.name='StreamPack' include ':core' include ':ui' +include ':services' // Extensions include ':extension-rtmp' diff --git a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/main/PreviewFragment.kt b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/main/PreviewFragment.kt index 346e883ef..76a3560c3 100644 --- a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/main/PreviewFragment.kt +++ b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/main/PreviewFragment.kt @@ -86,6 +86,7 @@ class PreviewFragment : Fragment() { ) -> { startStopLive() } + else -> { requestStreamerPermissionsLauncher.launch( permissions.toTypedArray() @@ -144,8 +145,9 @@ class PreviewFragment : Fragment() { requireContext(), Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO ) -> { - createStreamer() + configureStreamer() } + shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO) -> { showPermissionError() requestCameraAndMicrophonePermissionsLauncher.launch( @@ -154,6 +156,7 @@ class PreviewFragment : Fragment() { ) ) } + shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> { showPermissionError() requestCameraAndMicrophonePermissionsLauncher.launch( @@ -162,6 +165,7 @@ class PreviewFragment : Fragment() { ) ) } + else -> { requestCameraAndMicrophonePermissionsLauncher.launch( arrayOf( @@ -174,8 +178,8 @@ class PreviewFragment : Fragment() { } @RequiresPermission(Manifest.permission.RECORD_AUDIO) - private fun createStreamer() { - viewModel.createStreamer() + private fun configureStreamer() { + viewModel.configureStreamer() // Set camera settings button when camera is started binding.preview.listener = object : PreviewView.Listener { @@ -203,7 +207,7 @@ class PreviewFragment : Fragment() { if (permissions.toList().all { it.second }) { - createStreamer() + configureStreamer() } else { showPermissionErrorAndFinish() } diff --git a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/main/PreviewViewModel.kt b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/main/PreviewViewModel.kt index a68a39d45..7699b1537 100644 --- a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/main/PreviewViewModel.kt +++ b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/ui/main/PreviewViewModel.kt @@ -30,39 +30,48 @@ import io.github.thibaultbee.streampack.app.utils.ObservableViewModel import io.github.thibaultbee.streampack.app.utils.StreamerManager import io.github.thibaultbee.streampack.app.utils.isEmpty import io.github.thibaultbee.streampack.listeners.OnConnectionListener -import io.github.thibaultbee.streampack.listeners.OnErrorListener -import io.github.thibaultbee.streampack.streamers.StreamerLifeCycleObserver -import io.github.thibaultbee.streampack.utils.isFrameRateSupported +import io.github.thibaultbee.streampack.streamers.observers.StreamerLifeCycleObserver import io.github.thibaultbee.streampack.ui.views.PreviewView +import io.github.thibaultbee.streampack.utils.isFrameRateSupported +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch class PreviewViewModel(private val streamerManager: StreamerManager) : ObservableViewModel() { val streamerLifeCycleObserver: StreamerLifeCycleObserver get() = streamerManager.streamerLifeCycleObserver - val streamerError = MutableLiveData() + val streamerError: MutableLiveData = MutableLiveData() val requiredPermissions: List get() = streamerManager.requiredPermissions - private val onErrorListener = object : OnErrorListener { - override fun onError(e: Exception) { - Log.e(TAG, "onError", e) - streamerError.postValue("${e.javaClass.simpleName}: ${e.message}") + + init { + viewModelScope.launch { + streamerManager.exception.filterNotNull() + .map { "${it.javaClass.simpleName}: ${it.message}" }.collect { + streamerError.postValue(it) + } + } + viewModelScope.launch { + streamerManager.isOpened + .collect { + Log.i(TAG, "Streamer is opened: $it") + } + } + viewModelScope.launch { + streamerManager.isStreaming + .collect { + Log.i(TAG, "Streamer is streaming: $it") + } } } private val onConnectionListener = object : OnConnectionListener { override fun onLost(message: String) { - streamerError.postValue("Connection lost: $message") - } - - override fun onFailed(message: String) { - // Not needed as we catch startStream - } - - override fun onSuccess() { - Log.i(TAG, "Connection succeeded") + //streamerError.postValue("Connection lost: $message") } } @@ -79,12 +88,10 @@ class PreviewViewModel(private val streamerManager: StreamerManager) : Observabl } @RequiresPermission(Manifest.permission.RECORD_AUDIO) - fun createStreamer() { + fun configureStreamer() { viewModelScope.launch { try { - streamerManager.rebuildStreamer() - streamerManager.onErrorListener = onErrorListener - streamerManager.onConnectionListener = onConnectionListener + streamerManager.configureStreamer() Log.d(TAG, "Streamer is created") } catch (e: Throwable) { Log.e(TAG, "createStreamer failed", e) @@ -92,7 +99,7 @@ class PreviewViewModel(private val streamerManager: StreamerManager) : Observabl } } } - + fun startStream() { viewModelScope.launch { try { diff --git a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/Extensions.kt b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/Extensions.kt index 224de73c9..a6cacbefa 100644 --- a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/Extensions.kt +++ b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/Extensions.kt @@ -17,12 +17,12 @@ package io.github.thibaultbee.streampack.app.utils import android.content.ContentValues import android.content.Context +import android.net.Uri import android.os.Build import android.provider.MediaStore import android.util.Range -import java.io.OutputStream -fun Context.createVideoMediaOutputStream(name: String): OutputStream? { +fun Context.createVideoContentUri(name: String): Uri { val videoDetails = ContentValues().apply { put(MediaStore.Video.Media.TITLE, name) put( @@ -41,10 +41,16 @@ fun Context.createVideoMediaOutputStream(name: String): OutputStream? { MediaStore.Video.Media.EXTERNAL_CONTENT_URI } - val video = resolver.insert(collection, videoDetails) - ?: throw Exception("Unable to create video file") + return resolver.insert(collection, videoDetails) + ?: throw Exception("Unable to create video file: $name") +} - return resolver.openOutputStream(video) +fun String.appendIfNotEndsWith(suffix: String): String { + return if (this.endsWith(suffix)) { + this + } else { + this + suffix + } } val Range<*>.isEmpty: Boolean diff --git a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/StreamerFactory.kt b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/StreamerFactory.kt deleted file mode 100644 index 489fb9d4e..000000000 --- a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/StreamerFactory.kt +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.app.utils - -import android.Manifest -import android.content.Context -import android.util.Range -import androidx.annotation.RequiresPermission -import io.github.thibaultbee.streampack.app.configuration.Configuration -import io.github.thibaultbee.streampack.app.models.EndpointType -import io.github.thibaultbee.streampack.data.AudioConfig -import io.github.thibaultbee.streampack.data.BitrateRegulatorConfig -import io.github.thibaultbee.streampack.data.VideoConfig -import io.github.thibaultbee.streampack.ext.rtmp.streamers.AudioOnlyRtmpLiveStreamer -import io.github.thibaultbee.streampack.ext.rtmp.streamers.CameraRtmpLiveStreamer -import io.github.thibaultbee.streampack.ext.srt.regulator.srt.DefaultSrtBitrateRegulatorFactory -import io.github.thibaultbee.streampack.ext.srt.streamers.AudioOnlySrtLiveStreamer -import io.github.thibaultbee.streampack.ext.srt.streamers.CameraSrtLiveStreamer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.regulator.IBitrateRegulatorFactory -import io.github.thibaultbee.streampack.streamers.file.* -import io.github.thibaultbee.streampack.streamers.interfaces.IStreamer - -class StreamerFactory( - private val context: Context, - private val configuration: Configuration, -) { - private val enableAudio: Boolean - get() = configuration.audio.enable - - private val tsServiceInfo: TsServiceInfo - get() = TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, - 0x4698, - configuration.muxer.service, - configuration.muxer.provider - ) - - private val bitrateRegulatorFactory: IBitrateRegulatorFactory? - get() = if (configuration.endpoint.srt.enableBitrateRegulation) { - DefaultSrtBitrateRegulatorFactory() - } else { - null - } - - private val bitrateRegulatorConfig: BitrateRegulatorConfig? - get() = if (configuration.endpoint.srt.enableBitrateRegulation) { - BitrateRegulatorConfig( - configuration.endpoint.srt.videoBitrateRange, - Range(configuration.audio.bitrate, configuration.audio.bitrate) - ) - } else { - null - } - - - private fun createStreamer(context: Context): IStreamer { - return when { - configuration.video.enable -> { - when (configuration.endpoint.endpointType) { - EndpointType.TS_FILE -> CameraTsFileStreamer( - context, - enableAudio = enableAudio, - tsServiceInfo = tsServiceInfo - ) - - EndpointType.FLV_FILE -> CameraFlvFileStreamer( - context, - enableAudio = enableAudio - ) - - EndpointType.MP4_FILE -> CameraMp4FileStreamer( - context, - enableAudio = enableAudio - ) - - EndpointType.SRT -> CameraSrtLiveStreamer( - context, - enableAudio = enableAudio, - tsServiceInfo = tsServiceInfo, - bitrateRegulatorFactory = bitrateRegulatorFactory, - bitrateRegulatorConfig = bitrateRegulatorConfig - ) - - EndpointType.RTMP -> CameraRtmpLiveStreamer( - context, - enableAudio = enableAudio - ) - } - } - - configuration.audio.enable -> { - when (configuration.endpoint.endpointType) { - EndpointType.TS_FILE -> AudioOnlyTsFileStreamer( - context, - tsServiceInfo = tsServiceInfo - ) - - EndpointType.FLV_FILE -> AudioOnlyFlvFileStreamer(context) - EndpointType.MP4_FILE -> AudioOnlyMp4FileStreamer(context) - EndpointType.SRT -> AudioOnlySrtLiveStreamer( - context, - tsServiceInfo = tsServiceInfo - ) - - EndpointType.RTMP -> AudioOnlyRtmpLiveStreamer(context) - } - } - - else -> { - throw IllegalStateException("StreamerFactory: You must enable at least one of audio or video") - } - } - } - - @RequiresPermission(Manifest.permission.RECORD_AUDIO) - fun build(): IStreamer { - val streamer = createStreamer(context) - - val videoConfig = VideoConfig( - mimeType = configuration.video.encoder, - startBitrate = configuration.video.bitrate * 1000, // to b/s - resolution = configuration.video.resolution, - fps = configuration.video.fps, - profile = configuration.video.profile, - level = configuration.video.level - ) - - val audioConfig = AudioConfig( - mimeType = configuration.audio.encoder, - startBitrate = configuration.audio.bitrate, - sampleRate = configuration.audio.sampleRate, - channelConfig = AudioConfig.getChannelConfig(configuration.audio.numberOfChannels), - profile = configuration.audio.profile, - byteFormat = configuration.audio.byteFormat, - enableEchoCanceler = configuration.audio.enableEchoCanceler, - enableNoiseSuppressor = configuration.audio.enableNoiseSuppressor - ) - if (configuration.video.enable) { - streamer.configure(videoConfig) - } - - if (configuration.audio.enable) { - streamer.configure(audioConfig) - } - - return streamer - } -} \ No newline at end of file diff --git a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/StreamerManager.kt b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/StreamerManager.kt index 5ffcfe87d..d35bcbf86 100644 --- a/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/StreamerManager.kt +++ b/demos/camera/src/main/java/io/github/thibaultbee/streampack/app/utils/StreamerManager.kt @@ -18,57 +18,49 @@ package io.github.thibaultbee.streampack.app.utils import android.Manifest import android.content.Context import android.os.Build +import android.util.Range import androidx.annotation.RequiresPermission import io.github.thibaultbee.streampack.app.configuration.Configuration -import io.github.thibaultbee.streampack.ext.srt.data.SrtConnectionDescriptor -import io.github.thibaultbee.streampack.ext.srt.streamers.interfaces.ISrtLiveStreamer -import io.github.thibaultbee.streampack.internal.endpoints.composites.IPublicCompositeEndpoint -import io.github.thibaultbee.streampack.listeners.OnConnectionListener -import io.github.thibaultbee.streampack.listeners.OnErrorListener -import io.github.thibaultbee.streampack.streamers.StreamerLifeCycleObserver -import io.github.thibaultbee.streampack.streamers.interfaces.IStreamer -import io.github.thibaultbee.streampack.ui.views.PreviewView +import io.github.thibaultbee.streampack.app.models.EndpointType +import io.github.thibaultbee.streampack.app.models.FileExtension +import io.github.thibaultbee.streampack.data.AudioConfig +import io.github.thibaultbee.streampack.data.BitrateRegulatorConfig +import io.github.thibaultbee.streampack.data.VideoConfig +import io.github.thibaultbee.streampack.data.mediadescriptor.SrtMediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor +import io.github.thibaultbee.streampack.ext.srt.regulator.srt.SrtRegulatorController +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo import io.github.thibaultbee.streampack.internal.sources.video.camera.CameraSettings -import io.github.thibaultbee.streampack.utils.ChunkedFileOutputStream +import io.github.thibaultbee.streampack.streamers.DefaultCameraStreamer +import io.github.thibaultbee.streampack.streamers.interfaces.ICoroutineStreamer +import io.github.thibaultbee.streampack.streamers.observers.StreamerLifeCycleObserver +import io.github.thibaultbee.streampack.ui.views.PreviewView import io.github.thibaultbee.streampack.utils.backCameraList import io.github.thibaultbee.streampack.utils.frontCameraList import io.github.thibaultbee.streampack.utils.getCameraStreamer -import io.github.thibaultbee.streampack.utils.getFileStreamer -import io.github.thibaultbee.streampack.utils.getLiveStreamer -import io.github.thibaultbee.streampack.utils.getStreamer import io.github.thibaultbee.streampack.utils.isBackCamera +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.runBlocking -import java.io.File class StreamerManager( private val context: Context, private val configuration: Configuration ) { - private var streamer: IStreamer? = null + private val streamer: ICoroutineStreamer = + DefaultCameraStreamer(context, configuration.audio.enable) - var onErrorListener: OnErrorListener? - get() = streamer?.onErrorListener - set(value) { - streamer?.onErrorListener = value - } + val exception: StateFlow = streamer.exception - var onConnectionListener: OnConnectionListener? - get() = streamer?.getLiveStreamer()?.onConnectionListener - set(value) { - streamer?.getLiveStreamer()?.onConnectionListener = value - } + val isOpened: StateFlow = streamer.isOpened + + val isStreaming: StateFlow = streamer.isStreaming val cameraId: String? - get() = streamer?.getCameraStreamer()?.videoSource?.cameraId + get() = streamer.getCameraStreamer()?.videoSource?.cameraId val streamerLifeCycleObserver: StreamerLifeCycleObserver by lazy { - StreamerLifeCycleObserver(streamer!!) - } - - private fun getSrtLiveStreamer(): ISrtLiveStreamer? { - (streamer?.endpoint as IPublicCompositeEndpoint).muxer.info - return streamer?.getStreamer() + StreamerLifeCycleObserver(streamer) } val requiredPermissions: List @@ -77,75 +69,121 @@ class StreamerManager( Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO ) - streamer?.getFileStreamer()?.let { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE) - } + // Only needed for File (MP4, TS, FLV,...) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE) } return permissions } + private val tsServiceInfo: TSServiceInfo + get() = TSServiceInfo( + TSServiceInfo.ServiceType.DIGITAL_TV, + 0x4698, + configuration.muxer.service, + configuration.muxer.provider + ) + + private val bitrateRegulatorConfig: BitrateRegulatorConfig + get() = BitrateRegulatorConfig( + configuration.endpoint.srt.videoBitrateRange, + Range(configuration.audio.bitrate, configuration.audio.bitrate) + ) + @RequiresPermission(Manifest.permission.RECORD_AUDIO) - fun rebuildStreamer() { - streamer = StreamerFactory(context, configuration).build() + fun configureStreamer() { + val videoConfig = VideoConfig( + mimeType = configuration.video.encoder, + startBitrate = configuration.video.bitrate * 1000, // to b/s + resolution = configuration.video.resolution, + fps = configuration.video.fps, + profile = configuration.video.profile, + level = configuration.video.level + ) + + val audioConfig = AudioConfig( + mimeType = configuration.audio.encoder, + startBitrate = configuration.audio.bitrate, + sampleRate = configuration.audio.sampleRate, + channelConfig = AudioConfig.getChannelConfig(configuration.audio.numberOfChannels), + profile = configuration.audio.profile, + byteFormat = configuration.audio.byteFormat, + enableEchoCanceler = configuration.audio.enableEchoCanceler, + enableNoiseSuppressor = configuration.audio.enableNoiseSuppressor + ) + if (configuration.video.enable) { + streamer.configure(videoConfig) + } + + if (configuration.audio.enable) { + streamer.configure(audioConfig) + } } fun inflateStreamerView(view: PreviewView) { - view.streamer = streamer?.getCameraStreamer() + view.streamer = streamer.getCameraStreamer() } suspend fun startStream() { - if (streamer?.getLiveStreamer() != null) { - getSrtLiveStreamer()?.let { - val connection = SrtConnectionDescriptor( - configuration.endpoint.srt.ip, - configuration.endpoint.srt.port, - configuration.endpoint.srt.streamID, - configuration.endpoint.srt.passPhrase + + val descriptor = when (configuration.endpoint.endpointType) { + EndpointType.TS_FILE -> UriMediaDescriptor( + context.createVideoContentUri( + configuration.endpoint.file.filename.appendIfNotEndsWith( + FileExtension.TS.extension + ) + ) + ) + + EndpointType.FLV_FILE -> UriMediaDescriptor( + context.createVideoContentUri( + configuration.endpoint.file.filename.appendIfNotEndsWith( + FileExtension.FLV.extension + ) ) - it.connect( - connection + ) + + EndpointType.MP4_FILE -> UriMediaDescriptor( + context.createVideoContentUri( + configuration.endpoint.file.filename.appendIfNotEndsWith( + FileExtension.MP4.extension + ) ) - } ?: streamer?.getLiveStreamer()?.connect( - configuration.endpoint.rtmp.url ) + + EndpointType.SRT -> SrtMediaDescriptor( + configuration.endpoint.srt.ip, + configuration.endpoint.srt.port, + configuration.endpoint.srt.streamID, + configuration.endpoint.srt.passPhrase, + serviceInfo = tsServiceInfo + ) + + EndpointType.RTMP -> UriMediaDescriptor(configuration.endpoint.rtmp.url) } - streamer?.getFileStreamer()?.let { - /** - * Use OutputStream. - * FYI, outputStream is closed by stopStream. - * To cut the video into multiple parts/chunks, use [ChunkedFileOutputStream]. - */ - it.outputStream = - context.createVideoMediaOutputStream(configuration.endpoint.file.filename) - ?: throw Exception("Unable to create video output stream") - /** - * Or use [File]. - * It is not appropriate to directly access a [File]. Use Androidx FileProvider instead. - */ -// it.file = File( -// filesDir, -// configuration.endpoint.file.filename -// ) + if (configuration.endpoint.endpointType == EndpointType.SRT) { + if (configuration.endpoint.srt.enableBitrateRegulation) { + SrtRegulatorController(streamer, bitrateRegulatorConfig = bitrateRegulatorConfig) + } } - streamer?.startStream() + streamer.startStream(descriptor) } - fun stopStream() { + suspend fun stopStream() { runBlocking { - streamer?.stopStream() + streamer.stopStream() } - streamer?.getLiveStreamer()?.disconnect() + streamer.close() } fun release() { - streamer?.release() + streamer.release() } fun toggleCamera() { - streamer?.getCameraStreamer()?.let { + streamer.getCameraStreamer()?.let { // Handle devices with only one camera val cameras = if (context.isBackCamera(it.camera)) { context.frontCameraList @@ -159,12 +197,12 @@ class StreamerManager( } val cameraSettings: CameraSettings? - get() = streamer?.getCameraStreamer()?.videoSource?.settings + get() = streamer.getCameraStreamer()?.videoSource?.settings var isMuted: Boolean - get() = streamer?.audioSource?.isMuted ?: true + get() = streamer.audioSource?.isMuted ?: true set(value) { - streamer?.audioSource?.isMuted = value + streamer.audioSource?.isMuted = value } } \ No newline at end of file diff --git a/demos/screenrecorder/build.gradle b/demos/screenrecorder/build.gradle index 8a54e884d..476693d68 100644 --- a/demos/screenrecorder/build.gradle +++ b/demos/screenrecorder/build.gradle @@ -51,6 +51,7 @@ dependencies { implementation project(':core') implementation project(':extension-rtmp') implementation project(':extension-srt') + implementation project(':services') implementation "androidx.core:core-ktx:${androidxCoreVersion}" implementation 'androidx.appcompat:appcompat:1.6.1' diff --git a/demos/screenrecorder/src/main/AndroidManifest.xml b/demos/screenrecorder/src/main/AndroidManifest.xml index 20cf6fedd..9bd7edd3a 100644 --- a/demos/screenrecorder/src/main/AndroidManifest.xml +++ b/demos/screenrecorder/src/main/AndroidManifest.xml @@ -28,11 +28,7 @@ - diff --git a/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/Configuration.kt b/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/Configuration.kt index 2d0915e9f..daf659689 100644 --- a/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/Configuration.kt +++ b/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/Configuration.kt @@ -19,7 +19,6 @@ import android.content.Context import android.content.SharedPreferences import android.content.res.Resources import android.media.MediaFormat -import android.util.Range import android.util.Size import androidx.preference.PreferenceManager import io.github.thibaultbee.streampack.screenrecorder.models.EndpointType @@ -150,24 +149,6 @@ class Configuration(context: Context) { resources.getString(R.string.server_passphrase_key), field )!! - - var enableBitrateRegulation: Boolean = false - get() = sharedPref.getBoolean( - resources.getString(R.string.server_enable_bitrate_regulation_key), - field - ) - - var videoBitrateRange: Range = Range(300, 5000000) - get() = Range( - sharedPref.getInt( - resources.getString(R.string.server_video_min_bitrate_key), - field.lower - ) * 1000, // to b/s - sharedPref.getInt( - resources.getString(R.string.server_video_target_bitrate_key), - field.upper - ) * 1000, // to b/s - ) } class RtmpConnection( diff --git a/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/MainActivity.kt b/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/MainActivity.kt index d3000d42e..d6544c39f 100644 --- a/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/MainActivity.kt +++ b/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/MainActivity.kt @@ -32,23 +32,18 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import io.github.thibaultbee.streampack.data.AudioConfig -import io.github.thibaultbee.streampack.data.BitrateRegulatorConfig import io.github.thibaultbee.streampack.data.VideoConfig -import io.github.thibaultbee.streampack.ext.rtmp.services.ScreenRecorderRtmpLiveService -import io.github.thibaultbee.streampack.ext.srt.data.SrtConnectionDescriptor -import io.github.thibaultbee.streampack.ext.srt.services.ScreenRecorderSrtLiveService -import io.github.thibaultbee.streampack.ext.srt.streamers.interfaces.ISrtLiveStreamer +import io.github.thibaultbee.streampack.data.mediadescriptor.SrtMediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor import io.github.thibaultbee.streampack.internal.encoders.mediacodec.MediaCodecHelper -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo import io.github.thibaultbee.streampack.screenrecorder.databinding.ActivityMainBinding import io.github.thibaultbee.streampack.screenrecorder.models.EndpointType -import io.github.thibaultbee.streampack.screenrecorder.services.DemoScreenRecorderRtmpLiveService -import io.github.thibaultbee.streampack.screenrecorder.services.DemoScreenRecorderSrtLiveService +import io.github.thibaultbee.streampack.screenrecorder.services.DemoScreenRecorderService +import io.github.thibaultbee.streampack.screenrecorder.services.DemoScreenRecorderService.Companion.ENABLE_MICROPHONE_KEY import io.github.thibaultbee.streampack.screenrecorder.settings.SettingsActivity -import io.github.thibaultbee.streampack.streamers.bases.BaseScreenRecorderStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.ILiveStreamer -import io.github.thibaultbee.streampack.streamers.live.BaseScreenRecorderLiveStreamer -import io.github.thibaultbee.streampack.utils.getStreamer +import io.github.thibaultbee.streampack.services.DefaultScreenRecorderService +import io.github.thibaultbee.streampack.streamers.DefaultScreenRecorderStreamer import kotlinx.coroutines.runBlocking class MainActivity : AppCompatActivity() { @@ -56,7 +51,26 @@ class MainActivity : AppCompatActivity() { private val configuration by lazy { Configuration(this) } - private lateinit var streamer: BaseScreenRecorderLiveStreamer + private lateinit var streamer: DefaultScreenRecorderStreamer + + /** + * Custom bundle to pass to [DefaultScreenRecorderService]. + */ + private val customBundle: Bundle + get() { + return Bundle().apply { + putBoolean(ENABLE_MICROPHONE_KEY, configuration.audio.enable) + // Add other parameters here + } + } + + private val tsServiceInfo: TSServiceInfo + get() = TSServiceInfo( + TSServiceInfo.ServiceType.DIGITAL_TV, + 0x4698, + configuration.muxer.service, + configuration.muxer.provider + ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -89,7 +103,7 @@ class MainActivity : AppCompatActivity() { showPermissionAlertDialog(this) { this.finish() } } else { getContent.launch( - BaseScreenRecorderStreamer.createScreenRecorderIntent( + DefaultScreenRecorderStreamer.createScreenRecorderIntent( this ) ) @@ -98,76 +112,31 @@ class MainActivity : AppCompatActivity() { private var getContent = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - when (configuration.endpoint.type) { - EndpointType.SRT -> { - ScreenRecorderSrtLiveService.launch( - this, - DemoScreenRecorderSrtLiveService::class.java, - configuration.audio.enable, - TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, - 0x4698, - configuration.muxer.service, - configuration.muxer.provider - ), - configuration.endpoint.srt.enableBitrateRegulation, - BitrateRegulatorConfig(videoBitrateRange = configuration.endpoint.srt.videoBitrateRange), - { streamer -> - this.streamer = streamer.apply { - activityResult = result - } - try { - configureAndStart() - moveTaskToBack(true) - } catch (e: Exception) { - this@MainActivity.showAlertDialog( - this@MainActivity, - "Error", - e.message ?: "Unknown error" - ) - binding.liveButton.isChecked = false - Log.e(TAG, "Error while starting streamer", e) - } - }, - { - binding.liveButton.isChecked = false - Log.i(TAG, "Service disconnected") - }) - } - - EndpointType.RTMP -> { - ScreenRecorderRtmpLiveService.launch( - this, - DemoScreenRecorderRtmpLiveService::class.java, - configuration.audio.enable, - { streamer -> - this.streamer = streamer.apply { - activityResult = result - } - try { - configureAndStart() - moveTaskToBack(true) - } catch (e: Exception) { - this@MainActivity.showAlertDialog( - this@MainActivity, - "Error", - e.message ?: "Unknown error" - ) - binding.liveButton.isChecked = false - Log.e(TAG, "Error while starting streamer", e) - } - }, - { - this@MainActivity.showAlertDialog( - this@MainActivity, - "Error", - "Service disconnected" - ) - binding.liveButton.isChecked = false - Log.i(TAG, "Service disconnected") - }) - } - } + DefaultScreenRecorderService.launch( + this, + DemoScreenRecorderService::class.java, + customBundle, + { streamer -> + this.streamer = streamer.apply { + activityResult = result + } + try { + configureAndStart() + moveTaskToBack(true) + } catch (e: Exception) { + this@MainActivity.showAlertDialog( + this@MainActivity, + "Error", + e.message ?: "Unknown error" + ) + binding.liveButton.isChecked = false + Log.e(TAG, "Error while starting streamer", e) + } + }, + { + binding.liveButton.isChecked = false + Log.i(TAG, "Service disconnected") + }) } private fun configureAndStart() { @@ -215,43 +184,34 @@ class MainActivity : AppCompatActivity() { } runBlocking { - streamer.getStreamer()?.let { - val connection = SrtConnectionDescriptor( + val deescriptor = when (configuration.endpoint.type) { + EndpointType.SRT -> SrtMediaDescriptor( configuration.endpoint.srt.ip, configuration.endpoint.srt.port, configuration.endpoint.srt.streamID, - configuration.endpoint.srt.passPhrase + configuration.endpoint.srt.passPhrase, + serviceInfo = tsServiceInfo ) - it.connect(connection) - } ?: streamer.getStreamer()?.connect( - configuration.endpoint.rtmp.url - ) - streamer.startStream() + EndpointType.RTMP -> UriMediaDescriptor(configuration.endpoint.rtmp.url) + } + + streamer.startStream(deescriptor) } } private fun stopService() { runBlocking { streamer.stopStream() + streamer.close() } - streamer.disconnect() - when (configuration.endpoint.type) { - EndpointType.SRT -> stopService( - Intent( - this, - DemoScreenRecorderSrtLiveService::class.java - ) + stopService( + Intent( + this, + DemoScreenRecorderService::class.java ) - - EndpointType.RTMP -> stopService( - Intent( - this, - DemoScreenRecorderRtmpLiveService::class.java - ) - ) - } + ) } private fun showPopup() { diff --git a/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderRtmpLiveService.kt b/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderRtmpLiveService.kt deleted file mode 100644 index d2c930da1..000000000 --- a/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderRtmpLiveService.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.screenrecorder.services - -import android.app.Notification -import android.app.PendingIntent -import android.content.Intent -import androidx.core.app.NotificationCompat -import io.github.thibaultbee.streampack.ext.rtmp.services.ScreenRecorderRtmpLiveService -import io.github.thibaultbee.streampack.screenrecorder.R -import io.github.thibaultbee.streampack.screenrecorder.models.Actions -import kotlinx.coroutines.runBlocking - - -class DemoScreenRecorderRtmpLiveService : ScreenRecorderRtmpLiveService( - notificationId = 0x4568, - channelId = "io.github.thibaultbee.streampack.screenrecorder.demo.rtmp", - channelNameResourceId = R.string.app_name -) { - override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { - streamer?.let { - if (intent.action == Actions.STOP.value) { - runBlocking { - streamer?.stopStream() - } - } - } - return super.onStartCommand(intent, flags, startId) - } - - override fun onConnectionSuccessNotification(): Notification { - val intent = - Intent( - this, - DemoScreenRecorderRtmpLiveService::class.java - ).setAction(Actions.STOP.value) - val stopIntent = - PendingIntent.getService(this, 5678, intent, PendingIntent.FLAG_IMMUTABLE) - - return NotificationCompat.Builder(this, channelId) - .setSmallIcon(notificationIconResourceId) - .setContentTitle(getString(R.string.live_in_progress)) - .addAction( - R.drawable.ic_baseline_stop_24, - getString(R.string.stop), - stopIntent - ) - .build() - } -} \ No newline at end of file diff --git a/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderSrtLiveService.kt b/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderService.kt similarity index 50% rename from demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderSrtLiveService.kt rename to demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderService.kt index da1541427..6708ab855 100644 --- a/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderSrtLiveService.kt +++ b/demos/screenrecorder/src/main/java/io/github/thibaultbee/streampack/screenrecorder/services/DemoScreenRecorderService.kt @@ -15,34 +15,63 @@ */ package io.github.thibaultbee.streampack.screenrecorder.services +import android.Manifest import android.app.Notification import android.app.PendingIntent import android.content.Intent +import android.content.pm.PackageManager +import android.os.Bundle +import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat -import io.github.thibaultbee.streampack.ext.srt.services.ScreenRecorderSrtLiveService +import androidx.lifecycle.lifecycleScope import io.github.thibaultbee.streampack.screenrecorder.R import io.github.thibaultbee.streampack.screenrecorder.models.Actions -import kotlinx.coroutines.runBlocking +import io.github.thibaultbee.streampack.services.DefaultScreenRecorderService +import io.github.thibaultbee.streampack.streamers.DefaultScreenRecorderStreamer +import kotlinx.coroutines.launch -class DemoScreenRecorderSrtLiveService : ScreenRecorderSrtLiveService( +class DemoScreenRecorderService : DefaultScreenRecorderService( notificationId = 0x4569, - channelId = "io.github.thibaultbee.streampack.screenrecorder.demo.srt", + channelId = "io.github.thibaultbee.streampack.screenrecorder.demo", channelNameResourceId = R.string.app_name ) { - override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { - streamer?.let { - if (intent.action == Actions.STOP.value) { - runBlocking { - streamer?.stopStream() + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + if (intent != null) { + streamer?.let { + if (intent.action == Actions.STOP.value) { + lifecycleScope.launch { + streamer?.stopStream() + } } } } return super.onStartCommand(intent, flags, startId) } + /** + * Create a [DefaultScreenRecorderStreamer] with the custom [Bundle]. + */ + override fun createStreamer(bundle: Bundle): DefaultScreenRecorderStreamer { + val enableMicrophone = bundle.getBoolean(ENABLE_MICROPHONE_KEY, false) + if (enableMicrophone) { + if (ActivityCompat.checkSelfPermission( + this, + Manifest.permission.RECORD_AUDIO + ) != PackageManager.PERMISSION_GRANTED + ) { + throw SecurityException("Permission RECORD_AUDIO must have been granted!") + } + } + + return DefaultScreenRecorderStreamer( + applicationContext, + enableMicrophone = enableMicrophone, + ) + } + override fun onConnectionSuccessNotification(): Notification { val intent = - Intent(this, DemoScreenRecorderSrtLiveService::class.java).setAction(Actions.STOP.value) + Intent(this, DemoScreenRecorderService::class.java).setAction(Actions.STOP.value) val stopIntent = PendingIntent.getService(this, 5678, intent, PendingIntent.FLAG_IMMUTABLE) @@ -56,4 +85,9 @@ class DemoScreenRecorderSrtLiveService : ScreenRecorderSrtLiveService( ) .build() } + + companion object { + // Config + const val ENABLE_MICROPHONE_KEY = "enableMicrophone" + } } \ No newline at end of file diff --git a/extensions/rtmp/src/androidTest/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpConnectionDescriptorTest.kt b/extensions/rtmp/src/androidTest/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpMediaDescriptorTest.kt similarity index 86% rename from extensions/rtmp/src/androidTest/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpConnectionDescriptorTest.kt rename to extensions/rtmp/src/androidTest/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpMediaDescriptorTest.kt index b77f4cd73..76c915658 100644 --- a/extensions/rtmp/src/androidTest/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpConnectionDescriptorTest.kt +++ b/extensions/rtmp/src/androidTest/java/io/github/thibaultbee/streampack/ext/rtmp/data/RtmpMediaDescriptorTest.kt @@ -15,15 +15,16 @@ */ package io.github.thibaultbee.streampack.ext.rtmp.data +import io.github.thibaultbee.streampack.data.mediadescriptor.RtmpMediaDescriptor import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Test -class RtmpConnectionDescriptorTest { +class RtmpMediaDescriptorTest { @Test fun fromUrl() { val url = "rtmp://broadcast.host.com:1234/app/streamKey" - val connection = RtmpConnectionDescriptor.fromUrl(url) + val connection = RtmpMediaDescriptor.fromUrl(url) assertEquals("rtmp", connection.scheme) assertEquals("broadcast.host.com", connection.host) assertEquals(1234, connection.port) @@ -34,7 +35,7 @@ class RtmpConnectionDescriptorTest { @Test fun fromRtmpsUrl() { val url = "rtmps://broadcast.host.com:1234/app/streamKey" - val connection = RtmpConnectionDescriptor.fromUrl(url) + val connection = RtmpMediaDescriptor.fromUrl(url) assertEquals("rtmps", connection.scheme) assertEquals("broadcast.host.com", connection.host) assertEquals(1234, connection.port) @@ -45,7 +46,7 @@ class RtmpConnectionDescriptorTest { @Test fun fromUrlWithDefaultPort() { val url = "rtmp://broadcast.host.com/app/streamKey" - val connection = RtmpConnectionDescriptor.fromUrl(url) + val connection = RtmpMediaDescriptor.fromUrl(url) assertEquals("rtmp", connection.scheme) assertEquals("broadcast.host.com", connection.host) assertEquals(1935, connection.port) @@ -56,7 +57,7 @@ class RtmpConnectionDescriptorTest { @Test fun fromRtmpsUrlWithDefaultPort() { val url = "rtmps://broadcast.host.com/app/streamKey" - val connection = RtmpConnectionDescriptor.fromUrl(url) + val connection = RtmpMediaDescriptor.fromUrl(url) assertEquals("rtmps", connection.scheme) assertEquals("broadcast.host.com", connection.host) assertEquals(443, connection.port) @@ -68,7 +69,7 @@ class RtmpConnectionDescriptorTest { fun fromUrlWithBadScheme() { val url = "rtp://broadcast.host.com:1234/app/streamKey" try { - RtmpConnectionDescriptor.fromUrl(url) + RtmpMediaDescriptor.fromUrl(url) Assert.fail("Should throw an exception") } catch (_: Exception) { } diff --git a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/AudioOnlyRtmpLiveStreamer.kt b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/RtmpEndpoint.kt similarity index 50% rename from extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/AudioOnlyRtmpLiveStreamer.kt rename to extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/RtmpEndpoint.kt index d16628d44..e1643d6f7 100644 --- a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/AudioOnlyRtmpLiveStreamer.kt +++ b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/RtmpEndpoint.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Thibault B. + * Copyright (C) 2024 Thibault B. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,22 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.ext.rtmp.streamers +package io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.composites -import android.content.Context -import io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.sinks.RtmpSink -import io.github.thibaultbee.streampack.internal.endpoints.composites.ConnectableCompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.FlvMuxer -import io.github.thibaultbee.streampack.streamers.live.BaseAudioOnlyLiveStreamer +import io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.composites.sinks.RtmpSink +import io.github.thibaultbee.streampack.internal.endpoints.composites.CompositeEndpoint +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.flv.FlvMuxer /** - * A [BaseAudioOnlyLiveStreamer] that sends only microphone frames to a remote RTMP device. - * - * @param context application context + * A RTMP endpoint. + * It encapsulates a [FlvMuxer] and a [RtmpSink]. */ -class AudioOnlyRtmpLiveStreamer( - context: Context -) : BaseAudioOnlyLiveStreamer( - context = context, - internalEndpoint = ConnectableCompositeEndpoint(FlvMuxer(writeToFile = false), RtmpSink()) -) +class RtmpEndpoint : + CompositeEndpoint( + FlvMuxer( + isForFile = false + ), RtmpSink() + ) diff --git a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/sinks/RtmpSink.kt b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/sinks/RtmpSink.kt new file mode 100644 index 000000000..5cfdbc3c2 --- /dev/null +++ b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/sinks/RtmpSink.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2022 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.composites.sinks + +import io.github.thibaultbee.streampack.data.VideoConfig +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor +import io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.composites.sinks.utils.toRtmpUriMediaDescriptor +import io.github.thibaultbee.streampack.internal.data.Packet +import io.github.thibaultbee.streampack.internal.endpoints.MediaSinkType +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.EndpointConfiguration +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.ILiveSink +import io.github.thibaultbee.streampack.listeners.OnConnectionListener +import io.github.thibaultbee.streampack.logger.Logger +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.withContext +import video.api.rtmpdroid.Rtmp +import java.util.concurrent.Executors + +class RtmpSink( + private val dispatcher: CoroutineDispatcher = Executors.newSingleThreadExecutor() + .asCoroutineDispatcher() +) : ILiveSink { + override var onConnectionListener: OnConnectionListener? = null + + private var socket = Rtmp() + private var isOnError = false + + private val _isOpened = MutableStateFlow(false) + override val isOpened: StateFlow = _isOpened + + override fun configure(config: EndpointConfiguration) { + val videoConfig = config.streamConfigs.firstOrNull { it is VideoConfig } + if (videoConfig != null) { + socket.supportedVideoCodecs = listOf(videoConfig.mimeType) + } + } + + override suspend fun open(mediaDescriptor: MediaDescriptor) = + open(mediaDescriptor.toRtmpUriMediaDescriptor()) + + private suspend fun open(mediaDescriptor: UriMediaDescriptor) { + require(!isOpened.value) { "SrtEndpoint is already opened" } + require(mediaDescriptor.sinkType == MediaSinkType.RTMP) { "MediaDescriptor must be a rtmp Uri" } + + withContext(dispatcher) { + try { + isOnError = false + socket.connect("${mediaDescriptor.uri} live=1 flashver=FMLE/3.0\\20(compatible;\\20FMSc/1.0)") + _isOpened.emit(true) + } catch (e: Exception) { + socket = Rtmp() + _isOpened.emit(false) + throw e + } + } + } + + override suspend fun write(packet: Packet) = withContext(dispatcher) { + if (isOnError) { + return@withContext + } + + if (!(isOpened.value)) { + Logger.w(TAG, "Socket is not connected, dropping packet") + return@withContext + } + + try { + socket.write(packet.buffer) + } catch (e: Exception) { + close() + isOnError = true + _isOpened.emit(false) + Logger.e(TAG, "Error while writing packet to socket", e) + throw e + } + } + + override suspend fun startStream() { + withContext(dispatcher) { + socket.connectStream() + } + } + + override suspend fun stopStream() { + // No need to stop stream + } + + override suspend fun close() { + withContext(dispatcher) { + socket.close() + _isOpened.emit(false) + socket = Rtmp() + } + } + + companion object { + private const val TAG = "RtmpSink" + } +} diff --git a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/sinks/utils/Extensions.kt b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/sinks/utils/Extensions.kt new file mode 100644 index 000000000..f70ad650e --- /dev/null +++ b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/composites/sinks/utils/Extensions.kt @@ -0,0 +1,13 @@ +package io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.composites.sinks.utils + +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.RtmpMediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor + +fun MediaDescriptor.toRtmpUriMediaDescriptor(): UriMediaDescriptor { + return when (this) { + is UriMediaDescriptor -> this + is RtmpMediaDescriptor -> UriMediaDescriptor(this.uri) + else -> throw IllegalArgumentException("Unsupported MediaDescriptor: ${this::class.java.simpleName}") + } +} \ No newline at end of file diff --git a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/sinks/RtmpSink.kt b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/sinks/RtmpSink.kt deleted file mode 100644 index 9e587ab83..000000000 --- a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/internal/endpoints/sinks/RtmpSink.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.sinks - -import io.github.thibaultbee.streampack.ext.rtmp.data.RtmpConnectionDescriptor -import io.github.thibaultbee.streampack.internal.data.Packet -import io.github.thibaultbee.streampack.internal.endpoints.sinks.ILiveSink -import io.github.thibaultbee.streampack.listeners.OnConnectionListener -import io.github.thibaultbee.streampack.logger.Logger -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import video.api.rtmpdroid.Rtmp - -class RtmpSink( - private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO -) : ILiveSink { - override var onConnectionListener: OnConnectionListener? = null - - private var socket = Rtmp() - private var isOnError = false - - private var _isConnected = false - override val isConnected: Boolean - get() = _isConnected - - /** - * Sets/gets supported video codecs. - */ - var supportedVideoCodecs: List - get() = socket.supportedVideoCodecs - set(value) { - socket.supportedVideoCodecs = value - } - - override fun configure(config: Int) { - } - - override suspend fun connect(url: String) { - RtmpConnectionDescriptor.fromUrl(url) // URL validation - - withContext(coroutineDispatcher) { - try { - isOnError = false - socket.connect("$url live=1 flashver=FMLE/3.0\\20(compatible;\\20FMSc/1.0)") - _isConnected = true - onConnectionListener?.onSuccess() - } catch (e: Exception) { - socket = Rtmp() - _isConnected = false - onConnectionListener?.onFailed(e.message ?: "Unknown error") - throw e - } - } - } - - override fun disconnect() { - synchronized(this) { - socket.close() - _isConnected = false - socket = Rtmp() - } - } - - override fun write(packet: Packet) { - synchronized(this) { - if (isOnError) { - return - } - - if (!isConnected) { - Logger.w(TAG, "Socket is not connected, dropping packet") - return - } - - try { - socket.write(packet.buffer) - } catch (e: Exception) { - disconnect() - isOnError = true - _isConnected = false - onConnectionListener?.onLost(e.message ?: "Socket error") - Logger.e(TAG, "Error while writing packet to socket", e) - throw e - } - } - } - - override suspend fun startStream() { - withContext(coroutineDispatcher) { - synchronized(this) { - socket.connectStream() - } - } - } - - override suspend fun stopStream() { - // No need to stop stream - } - - override fun release() { - } - - companion object { - private const val TAG = "RtmpProducer" - } -} diff --git a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/services/ScreenRecorderRtmpLiveService.kt b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/services/ScreenRecorderRtmpLiveService.kt deleted file mode 100644 index 7f516b1fe..000000000 --- a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/services/ScreenRecorderRtmpLiveService.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.rtmp.services - -import android.content.ComponentName -import android.content.Context -import android.os.Bundle -import io.github.thibaultbee.streampack.R -import io.github.thibaultbee.streampack.ext.rtmp.streamers.ScreenRecorderRtmpLiveStreamer -import io.github.thibaultbee.streampack.streamers.bases.BaseScreenRecorderStreamer -import io.github.thibaultbee.streampack.streamers.services.BaseScreenRecorderService - -open class ScreenRecorderRtmpLiveService( - notificationId: Int = DEFAULT_NOTIFICATION_ID, - channelId: String = DEFAULT_NOTIFICATION_CHANNEL_ID, - channelNameResourceId: Int = R.string.default_channel_name, - channelDescriptionResourceId: Int = 0, -) : BaseScreenRecorderService( - notificationId, - channelId, - channelNameResourceId, - channelDescriptionResourceId -) { - override fun createStreamer(bundle: Bundle): BaseScreenRecorderStreamer { - val enableAudio = bundle.getBoolean(ENABLE_AUDIO_KEY) - - return ScreenRecorderRtmpLiveStreamer( - applicationContext, - enableAudio = enableAudio, - ) - } - - companion object { - /** - * Starts and binds the service with the appropriate parameters. - * - * @param context The application context. - * @param serviceClass The children service class. - * @param enableAudio [Boolean.true] to also capture audio. False to disable audio capture. - * @param onServiceCreated Callback that returns the [ScreenRecorderRtmpLiveStreamer] instance when the service has been connected. - * @param onServiceDisconnected Callback that will be called when the service is disconnected. - */ - fun launch( - context: Context, - serviceClass: Class, - enableAudio: Boolean, - onServiceCreated: (ScreenRecorderRtmpLiveStreamer) -> Unit, - onServiceDisconnected: (name: ComponentName?) -> Unit - ) { - BaseScreenRecorderService.launch( - context, - serviceClass, - enableAudio, - { streamer -> onServiceCreated(streamer as ScreenRecorderRtmpLiveStreamer) }, - onServiceDisconnected - ) - } - } -} \ No newline at end of file diff --git a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/CameraRtmpLiveStreamer.kt b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/CameraRtmpLiveStreamer.kt deleted file mode 100644 index 1191cdaa1..000000000 --- a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/CameraRtmpLiveStreamer.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.rtmp.streamers - -import android.content.Context -import io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.sinks.RtmpSink -import io.github.thibaultbee.streampack.internal.endpoints.composites.ConnectableCompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.FlvMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video.ExtendedVideoTag -import io.github.thibaultbee.streampack.streamers.live.BaseCameraLiveStreamer - -/** - * A [BaseCameraLiveStreamer] that sends microphone and camera frames to a remote RTMP device. - * - * @param context application context - * @param enableAudio [Boolean.true] to capture audio. False to disable audio capture. - */ -class CameraRtmpLiveStreamer( - context: Context, - enableAudio: Boolean = true -) : BaseCameraLiveStreamer( - context = context, - enableAudio = enableAudio, - internalEndpoint = ConnectableCompositeEndpoint(FlvMuxer(writeToFile = false), RtmpSink()) -) { - private val rtmpProducer = (internalEndpoint as ConnectableCompositeEndpoint).sink as RtmpSink - - override suspend fun connect(url: String) { - require(videoConfig != null) { - "Video config must be set before connecting to send the video codec in the connect message" - } - val codecMimeType = videoConfig!!.mimeType - if (ExtendedVideoTag.isSupportedCodec(codecMimeType)) { - rtmpProducer.supportedVideoCodecs = listOf(codecMimeType) - } - rtmpProducer.supportedVideoCodecs = listOf(videoConfig!!.mimeType) - super.connect(url) - } -} diff --git a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/ScreenRecorderRtmpLiveStreamer.kt b/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/ScreenRecorderRtmpLiveStreamer.kt deleted file mode 100644 index b3dcb15b3..000000000 --- a/extensions/rtmp/src/main/java/io/github/thibaultbee/streampack/ext/rtmp/streamers/ScreenRecorderRtmpLiveStreamer.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.rtmp.streamers - -import android.app.Service -import android.content.Context -import io.github.thibaultbee.streampack.ext.rtmp.internal.endpoints.sinks.RtmpSink -import io.github.thibaultbee.streampack.internal.endpoints.composites.ConnectableCompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.FlvMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.flv.tags.video.ExtendedVideoTag -import io.github.thibaultbee.streampack.streamers.bases.BaseScreenRecorderStreamer -import io.github.thibaultbee.streampack.streamers.live.BaseScreenRecorderLiveStreamer - -/** - * A [BaseScreenRecorderStreamer] that sends microphone and screen frames to a remote RTMP device. - * To run this streamer while application is on background, you will have to create a [Service]. - * As an example, check for `screenrecorder` application. - * - * @param context application context - * @param enableAudio [Boolean.true] to also capture audio. False to disable audio capture - */ -class ScreenRecorderRtmpLiveStreamer( - context: Context, - enableAudio: Boolean = true -) : BaseScreenRecorderLiveStreamer( - context = context, - enableAudio = enableAudio, - internalEndpoint = ConnectableCompositeEndpoint(FlvMuxer(writeToFile = false), RtmpSink()) -) { - private val rtmpProducer = (internalEndpoint as ConnectableCompositeEndpoint).sink as RtmpSink - - override suspend fun connect(url: String) { - require(videoConfig != null) { - "Video config must be set before connecting to send the video codec in the connect message" - } - val codecMimeType = videoConfig!!.mimeType - if (ExtendedVideoTag.isSupportedCodec(codecMimeType)) { - rtmpProducer.supportedVideoCodecs = listOf(codecMimeType) - } - rtmpProducer.supportedVideoCodecs = listOf(videoConfig!!.mimeType) - super.connect(url) - } -} \ No newline at end of file diff --git a/extensions/srt/src/androidTest/java/io/github/thibaultbee/streampack/ext/srt/data/SrtConnectionDescriptorTest.kt b/extensions/srt/src/androidTest/java/io/github/thibaultbee/streampack/ext/srt/data/SrtMediaDescriptorTest.kt similarity index 84% rename from extensions/srt/src/androidTest/java/io/github/thibaultbee/streampack/ext/srt/data/SrtConnectionDescriptorTest.kt rename to extensions/srt/src/androidTest/java/io/github/thibaultbee/streampack/ext/srt/data/SrtMediaDescriptorTest.kt index 864336150..1bba2c1c5 100644 --- a/extensions/srt/src/androidTest/java/io/github/thibaultbee/streampack/ext/srt/data/SrtConnectionDescriptorTest.kt +++ b/extensions/srt/src/androidTest/java/io/github/thibaultbee/streampack/ext/srt/data/SrtMediaDescriptorTest.kt @@ -15,15 +15,16 @@ */ package io.github.thibaultbee.streampack.ext.srt.data +import io.github.thibaultbee.streampack.data.mediadescriptor.SrtMediaDescriptor import org.junit.Assert.assertEquals import org.junit.Assert.fail import org.junit.Test -class SrtConnectionDescriptorTest { +class SrtMediaDescriptorTest { @Test fun fromUrl() { val url = "srt://broadcast.host.com:1234" - val connection = SrtConnectionDescriptor.fromUrl(url) + val connection = SrtMediaDescriptor.fromUrl(url) assertEquals("broadcast.host.com", connection.host) assertEquals(1234, connection.port) } @@ -31,7 +32,7 @@ class SrtConnectionDescriptorTest { @Test fun fromIp() { val url = "srt://192.168.1.12:1234" - val connection = SrtConnectionDescriptor.fromUrl(url) + val connection = SrtMediaDescriptor.fromUrl(url) assertEquals("192.168.1.12", connection.host) assertEquals(1234, connection.port) } @@ -39,7 +40,7 @@ class SrtConnectionDescriptorTest { @Test fun fromUrlWithParameters() { val url = "srt://host.com:1234?streamid=streamId&passphrase=passPhrase" - val connection = SrtConnectionDescriptor.fromUrl(url) + val connection = SrtMediaDescriptor.fromUrl(url) assertEquals("host.com", connection.host) assertEquals(1234, connection.port) assertEquals("streamId", connection.streamId) @@ -50,7 +51,7 @@ class SrtConnectionDescriptorTest { fun fromUrlWithBadScheme() { val url = "srtp://broadcast.host.com:1234" try { - SrtConnectionDescriptor.fromUrl(url) + SrtMediaDescriptor.fromUrl(url) fail("Should throw an exception") } catch (_: Exception) { } @@ -60,7 +61,7 @@ class SrtConnectionDescriptorTest { fun fromUrlWithUnknownParam() { val url = "srt://host.com:1234?streamid=streamId&passphrase=passPhrase&unknown=unknown" try { - SrtConnectionDescriptor.fromUrl(url) + SrtMediaDescriptor.fromUrl(url) } catch (e: Exception) { assertEquals("Failed to parse URL $url: unknown parameter(s): unknown", e.message) } diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/SrtEndpoint.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/SrtEndpoint.kt new file mode 100644 index 000000000..2bcfb83ca --- /dev/null +++ b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/SrtEndpoint.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.ext.srt.internal.endpoints.composites + +import io.github.thibaultbee.streampack.data.mediadescriptor.createDefaultTsServiceInfo +import io.github.thibaultbee.streampack.ext.srt.internal.endpoints.composites.sinks.SrtSink +import io.github.thibaultbee.streampack.internal.endpoints.composites.CompositeEndpoint +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.TSMuxer +import io.github.thibaultbee.streampack.internal.endpoints.composites.muxers.ts.data.TSServiceInfo + +/** + * Creates a [SrtEndpoint] with a default [TSServiceInfo]. + */ +fun SrtEndpoint(serviceInfo: TSServiceInfo = createDefaultTsServiceInfo()) = SrtEndpoint().apply { + addService(serviceInfo) +} + +/** + * A SRT endpoint. + * It encapsulates a [TSMuxer] and a [SrtSink]. + */ +class SrtEndpoint : + CompositeEndpoint(TSMuxer(), SrtSink()) { + fun addService(serviceInfo: TSServiceInfo = createDefaultTsServiceInfo()) { + (muxer as TSMuxer).addService(serviceInfo) + } + + fun removeService(serviceInfo: TSServiceInfo) { + (muxer as TSMuxer).removeService(serviceInfo) + } +} \ No newline at end of file diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/sinks/SrtSink.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/sinks/SrtSink.kt similarity index 61% rename from extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/sinks/SrtSink.kt rename to extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/sinks/SrtSink.kt index 6eed09635..7b640bd8d 100644 --- a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/sinks/SrtSink.kt +++ b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/sinks/SrtSink.kt @@ -1,6 +1,20 @@ -package io.github.thibaultbee.streampack.ext.srt.internal.endpoints.sinks +/* + * Copyright (C) 2024 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.ext.srt.internal.endpoints.composites.sinks -import io.github.thibaultbee.srtdroid.Srt import io.github.thibaultbee.srtdroid.enums.Boundary import io.github.thibaultbee.srtdroid.enums.ErrorType import io.github.thibaultbee.srtdroid.enums.SockOpt @@ -9,15 +23,19 @@ import io.github.thibaultbee.srtdroid.listeners.SocketListener import io.github.thibaultbee.srtdroid.models.MsgCtrl import io.github.thibaultbee.srtdroid.models.Socket import io.github.thibaultbee.srtdroid.models.Stats -import io.github.thibaultbee.streampack.ext.srt.data.SrtConnectionDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.SrtMediaDescriptor +import io.github.thibaultbee.streampack.ext.srt.internal.endpoints.composites.sinks.utils.toSrtConnectionDescriptor import io.github.thibaultbee.streampack.internal.data.Packet import io.github.thibaultbee.streampack.internal.data.SrtPacket -import io.github.thibaultbee.streampack.internal.endpoints.sinks.ILiveSink +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.EndpointConfiguration +import io.github.thibaultbee.streampack.internal.endpoints.composites.sinks.ILiveSink import io.github.thibaultbee.streampack.listeners.OnConnectionListener import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext -import java.net.ConnectException import java.net.InetSocketAddress class SrtSink( @@ -32,31 +50,29 @@ class SrtSink( /** * Get/set SRT stream ID */ - var streamId: String + private var streamId: String get() = socket.getSockFlag(SockOpt.STREAMID) as String - @Deprecated("Use SrtConnectionDescriptor.streamId instead") - set(value) = socket.setSockFlag(SockOpt.STREAMID, value) + private set(value) = socket.setSockFlag(SockOpt.STREAMID, value) /** * Get/set SRT stream passPhrase * It is a set only parameter, so getting the value throws an exception. */ - var passPhrase: String + private var passPhrase: String get() = socket.getSockFlag(SockOpt.PASSPHRASE) as String - @Deprecated("Use SrtConnectionDescriptor.passPhrase instead") - set(value) = socket.setSockFlag(SockOpt.PASSPHRASE, value) + private set(value) = socket.setSockFlag(SockOpt.PASSPHRASE, value) /** * Get/set bidirectional latency in milliseconds */ - var latency: Int + private var latency: Int get() = socket.getSockFlag(SockOpt.LATENCY) as Int private set(value) = socket.setSockFlag(SockOpt.LATENCY, value) /** * Get/set connection timeout in milliseconds */ - var connectionTimeout: Int + private var connectionTimeout: Int get() = socket.getSockFlag(SockOpt.CONNTIMEO) as Int private set(value) = socket.setSockFlag(SockOpt.CONNTIMEO, value) @@ -66,16 +82,20 @@ class SrtSink( val stats: Stats get() = socket.bistats(clear = true, instantaneous = true) - override val isConnected: Boolean - get() = socket.isConnected + private val _isOpened = MutableStateFlow(false) + override val isOpened: StateFlow = _isOpened - override fun configure(config: Int) { - this.bitrate = config.toLong() + override fun configure(config: EndpointConfiguration) { + bitrate = config.streamConfigs.sumOf { it.startBitrate.toLong() } } - override suspend fun connect(url: String) = connect(SrtConnectionDescriptor.fromUrl(url)) + override suspend fun open( + mediaDescriptor: MediaDescriptor + ) = open(mediaDescriptor.toSrtConnectionDescriptor()) + + private suspend fun open(mediaDescriptor: SrtMediaDescriptor) { + require(!isOpened.value) { "SrtEndpoint is already opened" } - suspend fun connect(connection: SrtConnectionDescriptor) { withContext(coroutineDispatcher) { try { socket.listener = object : SocketListener { @@ -99,28 +119,22 @@ class SrtSink( socket.setSockFlag(SockOpt.PAYLOADSIZE, PAYLOAD_SIZE) socket.setSockFlag(SockOpt.TRANSTYPE, Transtype.LIVE) - connection.streamId?.let { streamId = it } - connection.passPhrase?.let { passPhrase = it } - connection.latency?.let { latency = it } - connection.connectionTimeout?.let { connectionTimeout = it } + mediaDescriptor.streamId?.let { streamId = it } + mediaDescriptor.passPhrase?.let { passPhrase = it } + mediaDescriptor.latency?.let { latency = it } + mediaDescriptor.connectionTimeout?.let { connectionTimeout = it } isOnError = false - socket.connect(connection.host, connection.port) - onConnectionListener?.onSuccess() + socket.connect(mediaDescriptor.host, mediaDescriptor.port) + _isOpened.emit(true) } catch (e: Exception) { socket = Socket() - onConnectionListener?.onFailed(e.message ?: "Unknown error") throw e } } } - override fun disconnect() { - socket.close() - socket = Socket() - } - - override fun write(packet: Packet) { + override suspend fun write(packet: Packet) { if (isOnError) return packet as SrtPacket @@ -144,28 +158,29 @@ class SrtSink( try { socket.send(packet.buffer, msgCtrl) } catch (e: Exception) { + _isOpened.emit(false) isOnError = true throw e } } override suspend fun startStream() { - if (!socket.isConnected) { - throw ConnectException("SrtEndpoint should be connected at this point") - } + require(socket.isConnected) { "SrtEndpoint should be connected at this point" } socket.setSockFlag(SockOpt.MAXBW, 0L) socket.setSockFlag(SockOpt.INPUTBW, bitrate) } override suspend fun stopStream() { - } - override fun release() { - Srt.cleanUp() + override suspend fun close() { + socket.close() + _isOpened.emit(false) + socket = Socket() } + companion object { private const val PAYLOAD_SIZE = 1316 } diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/sinks/utils/Extensions.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/sinks/utils/Extensions.kt new file mode 100644 index 000000000..c60e5b216 --- /dev/null +++ b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/internal/endpoints/composites/sinks/utils/Extensions.kt @@ -0,0 +1,13 @@ +package io.github.thibaultbee.streampack.ext.srt.internal.endpoints.composites.sinks.utils + +import io.github.thibaultbee.streampack.data.mediadescriptor.MediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.SrtMediaDescriptor +import io.github.thibaultbee.streampack.data.mediadescriptor.UriMediaDescriptor + +fun MediaDescriptor.toSrtConnectionDescriptor(): SrtMediaDescriptor { + return when (this) { + is SrtMediaDescriptor -> this + is UriMediaDescriptor -> SrtMediaDescriptor.fromUri(uri) + else -> throw IllegalArgumentException("Unsupported MediaDescriptor: ${this::class.java.simpleName}") + } +} \ No newline at end of file diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/regulator/srt/SrtRegulatorController.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/regulator/srt/SrtRegulatorController.kt new file mode 100644 index 000000000..1a588a826 --- /dev/null +++ b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/regulator/srt/SrtRegulatorController.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2021 Thibault B. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.thibaultbee.streampack.ext.srt.regulator.srt + +import io.github.thibaultbee.streampack.data.BitrateRegulatorConfig +import io.github.thibaultbee.streampack.ext.srt.internal.endpoints.composites.sinks.SrtSink +import io.github.thibaultbee.streampack.internal.endpoints.composites.CompositeEndpoint +import io.github.thibaultbee.streampack.internal.utils.Scheduler +import io.github.thibaultbee.streampack.regulator.IBitrateRegulatorFactory +import io.github.thibaultbee.streampack.streamers.interfaces.ICoroutineStreamer +import kotlinx.coroutines.runBlocking + +/** + * SrtStreamerRegulator is a helper class to regulate bitrate of a [ICoroutineStreamer] using SRT. + * + * @param streamer the [ICoroutineStreamer] implementation. + * @param bitrateRegulatorFactory the [IBitrateRegulatorFactory] implementation. Use it to make your own bitrate regulator. + * @param bitrateRegulatorConfig bitrate regulator configuration + */ +class SrtRegulatorController( + val streamer: ICoroutineStreamer, + bitrateRegulatorFactory: IBitrateRegulatorFactory = DefaultSrtBitrateRegulatorFactory(), + bitrateRegulatorConfig: BitrateRegulatorConfig = BitrateRegulatorConfig() +) { + /** + * Bitrate regulator. Calls regularly by [scheduler]. Don't call it otherwise or you might break regulation. + */ + private val bitrateRegulator = bitrateRegulatorConfig.let { config -> + bitrateRegulatorFactory.newBitrateRegulator( + config, + { + val videoEncoder = streamer.videoEncoder + ?: throw UnsupportedOperationException("Bitrate regulator set without a video encoder") + videoEncoder.bitrate = it + }, + { /* Do nothing for audio */ } + ) as SrtBitrateRegulator + } + + /** + * Scheduler for bitrate regulation + */ + private val scheduler = Scheduler(500) { + val videoEncoder = streamer.videoEncoder + ?: throw UnsupportedOperationException("Scheduler runs but no video encoder set") + bitrateRegulator.update( + srtSink.stats, + videoEncoder.bitrate, + streamer.audioEncoder?.bitrate ?: 0 + ) + } + + private val srtSink = (streamer.endpoint as CompositeEndpoint).sink as SrtSink + + init { + // TODO: use streamer scope + runBlocking { + streamer.isStreaming.collect { isStreaming -> + if (isStreaming) { + scheduler.start() + } else { + scheduler.cancel() + } + } + } + } +} diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/services/ScreenRecorderSrtLiveService.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/services/ScreenRecorderSrtLiveService.kt deleted file mode 100644 index 69ae8d688..000000000 --- a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/services/ScreenRecorderSrtLiveService.kt +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2022 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.srt.services - -import android.content.ComponentName -import android.content.Context -import android.os.Bundle -import android.util.Range -import io.github.thibaultbee.streampack.R -import io.github.thibaultbee.streampack.data.BitrateRegulatorConfig -import io.github.thibaultbee.streampack.ext.srt.regulator.srt.DefaultSrtBitrateRegulatorFactory -import io.github.thibaultbee.streampack.ext.srt.streamers.ScreenRecorderSrtLiveStreamer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.utils.extensions.defaultTsServiceInfo -import io.github.thibaultbee.streampack.streamers.bases.BaseScreenRecorderStreamer -import io.github.thibaultbee.streampack.streamers.services.BaseScreenRecorderService - -open class ScreenRecorderSrtLiveService( - notificationId: Int = DEFAULT_NOTIFICATION_ID, - channelId: String = DEFAULT_NOTIFICATION_CHANNEL_ID, - channelNameResourceId: Int = R.string.default_channel_name, - channelDescriptionResourceId: Int = 0, -) : BaseScreenRecorderService( - notificationId, - channelId, - channelNameResourceId, - channelDescriptionResourceId -) { - - override fun createStreamer(bundle: Bundle): BaseScreenRecorderStreamer { - val enableAudio = bundle.getBoolean(ENABLE_AUDIO_KEY) - - val muxerConfigBundle = bundle.getBundle(MUXER_CONFIG_KEY) - val tsServiceInfo = TsServiceInfo( - TsServiceInfo.ServiceType.DIGITAL_TV, - 0x4698, - muxerConfigBundle?.getString(SERVICE_NAME) - ?: getString(R.string.ts_service_default_name), - muxerConfigBundle?.getString(SERVICE_PROVIDER_NAME) - ?: getString(R.string.ts_service_default_provider_name), - ) - - val endpointConfigBundle = bundle.getBundle(ENDPOINT_CONFIG_KEY) - val enableBitrateRegulation = - endpointConfigBundle?.getBoolean(ENABLE_BITRATE_REGULATION, false) ?: false - - val videoBitrateRange = if (enableBitrateRegulation) { - if (!endpointConfigBundle!!.containsKey(VIDEO_BITRATE_REGULATION_LOWER) or !endpointConfigBundle.containsKey( - VIDEO_BITRATE_REGULATION_UPPER - ) - ) { - throw IllegalStateException("If bitrate regulation is enabled, video bitrate regulation must be set") - } - Range( - endpointConfigBundle.getInt(VIDEO_BITRATE_REGULATION_LOWER), - endpointConfigBundle.getInt(VIDEO_BITRATE_REGULATION_UPPER) - ) - } else { - null - } - - val bitrateRegulatorFactory = if (enableBitrateRegulation) { - DefaultSrtBitrateRegulatorFactory() - } else { - null - } - val bitrateRegulatorConfig = if (enableBitrateRegulation) { - BitrateRegulatorConfig( - videoBitrateRange!!, // if enableBitrateRegulation = true, videoBitrateRange exists - Range( - 128000, - 128000 - ) // Not used for now, but we need to set it to something - ) - } else { - null - } - - return ScreenRecorderSrtLiveStreamer( - applicationContext, - enableAudio = enableAudio, - tsServiceInfo = tsServiceInfo, - bitrateRegulatorFactory = bitrateRegulatorFactory, - bitrateRegulatorConfig = bitrateRegulatorConfig - ) - } - - companion object { - // Muxer config - const val SERVICE_PROVIDER_NAME = "providerName" - const val SERVICE_NAME = "name" - - // Endpoint - const val ENABLE_BITRATE_REGULATION = "enableBitrateRegulation" - const val VIDEO_BITRATE_REGULATION_LOWER = "bitrateRegulationLower" - const val VIDEO_BITRATE_REGULATION_UPPER = "bitrateRegulationUpper" - - /** - * Starts and binds the service with the appropriate parameters. - * - * @param context The application context. - * @param serviceClass The children service class. - * @param enableAudio [Boolean.true] to also capture audio. [Boolean.false] to disable audio capture. - * @param tsServiceInfo MPEG-TS service description - * @param enableBitrateRegulation [Boolean.true] to enable bitrate regulation. [Boolean.false] to disable bitrate regulation. - * @param bitrateRegulatorConfig bitrate regulator configuration. If bitrateRegulatorFactory is not null, bitrateRegulatorConfig must not be null. - * @param onServiceCreated Callback that returns the [ScreenRecorderSrtLiveStreamer] instance when the service has been connected. - * @param onServiceDisconnected Callback that will be called when the service is disconnected. - */ - fun launch( - context: Context, - serviceClass: Class, - enableAudio: Boolean = true, - tsServiceInfo: TsServiceInfo = context.defaultTsServiceInfo, - enableBitrateRegulation: Boolean = false, - bitrateRegulatorConfig: BitrateRegulatorConfig? = null, - onServiceCreated: (ScreenRecorderSrtLiveStreamer) -> Unit, - onServiceDisconnected: (name: ComponentName?) -> Unit - ) { - val constructorBundle = Bundle().apply { - putBoolean(ENABLE_AUDIO_KEY, enableAudio) - - putBundle(MUXER_CONFIG_KEY, Bundle().apply { - putString(SERVICE_PROVIDER_NAME, tsServiceInfo.providerName) - putString(SERVICE_NAME, tsServiceInfo.name) - }) - - putBundle(ENDPOINT_CONFIG_KEY, Bundle().apply { - putBoolean(ENABLE_BITRATE_REGULATION, enableBitrateRegulation) - if (enableBitrateRegulation) { - require(bitrateRegulatorConfig != null) { "If bitrate regulation is enabled, bitrateRegulatorConfig must be set" } - putInt( - VIDEO_BITRATE_REGULATION_LOWER, - bitrateRegulatorConfig.videoBitrateRange.lower - ) - putInt( - VIDEO_BITRATE_REGULATION_UPPER, - bitrateRegulatorConfig.videoBitrateRange.upper - ) - } - }) - } - - launch( - context, - serviceClass, - constructorBundle, - { streamer -> onServiceCreated(streamer as ScreenRecorderSrtLiveStreamer) }, - onServiceDisconnected - ) - } - } -} \ No newline at end of file diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/AudioOnlySrtLiveStreamer.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/AudioOnlySrtLiveStreamer.kt deleted file mode 100644 index 633075e7a..000000000 --- a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/AudioOnlySrtLiveStreamer.kt +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.srt.streamers - -import android.content.Context -import io.github.thibaultbee.streampack.ext.srt.data.SrtConnectionDescriptor -import io.github.thibaultbee.streampack.ext.srt.internal.endpoints.sinks.SrtSink -import io.github.thibaultbee.streampack.ext.srt.streamers.interfaces.ISrtLiveStreamer -import io.github.thibaultbee.streampack.internal.endpoints.composites.ConnectableCompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.utils.extensions.defaultTsServiceInfo -import io.github.thibaultbee.streampack.streamers.live.BaseAudioOnlyLiveStreamer - -/** - * A [BaseAudioOnlyLiveStreamer] that sends only microphone frames to a remote Secure Reliable Transport - * (SRT) device. - * - * @param context application context - * @param tsServiceInfo MPEG-TS service description - */ -class AudioOnlySrtLiveStreamer( - context: Context, - tsServiceInfo: TsServiceInfo = context.defaultTsServiceInfo -) : BaseAudioOnlyLiveStreamer( - context = context, - internalEndpoint = ConnectableCompositeEndpoint( - TSMuxer().apply { addService(tsServiceInfo) }, - SrtSink() - ), -), - ISrtLiveStreamer { - private val srtProducer = (internalEndpoint as ConnectableCompositeEndpoint).sink as SrtSink - - /** - * Get/set SRT stream ID. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#srto_streamid) - */ - override var streamId: String - /** - * Get SRT stream ID - * @return stream ID - */ - get() = srtProducer.streamId - /** - * @param value stream ID - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - set(value) { - srtProducer.streamId = value - } - - /** - * Get/set SRT passphrase. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#srto_passphrase) - */ - override var passPhrase: String - /** - * Get SRT passphrase - * @return passphrase - */ - get() = srtProducer.passPhrase - /** - * @param value passphrase - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - set(value) { - srtProducer.passPhrase = value - } - - /** - * Get/set bidirectional latency in milliseconds. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#SRTO_LATENCY) - */ - override val latency: Int - /** - * Get latency in milliseconds - * @return latency - */ - get() = srtProducer.latency - - /** - * Connect to an SRT server with correct Live streaming parameters. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param ip server ip - * @param port server port - * @throws Exception if connection has failed or configuration has failed - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - override suspend fun connect(ip: String, port: Int) { - val connection = SrtConnectionDescriptor(ip, port) - srtProducer.connect(connection) - } - - /** - * Connect to an SRT server with correct Live streaming parameters. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param connection the SRT connection - * @throws Exception if connection has failed or configuration has failed - */ - override suspend fun connect(connection: SrtConnectionDescriptor) { - srtProducer.connect(connection) - } - - /** - * Connect to an SRT server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param ip server ip - * @param port server port - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - @Deprecated( - "Use the new startStream(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("startStream(SrtConnectionDescriptor)") - ) - override suspend fun startStream(ip: String, port: Int) { - val connection = SrtConnectionDescriptor(ip, port) - startStream(connection) - } - - /** - * Connect to an SRT server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param connection the SRT connection - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - override suspend fun startStream(connection: SrtConnectionDescriptor) { - connect(connection) - startStream() - } -} diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/CameraSrtLiveStreamer.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/CameraSrtLiveStreamer.kt deleted file mode 100644 index 9ada6e107..000000000 --- a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/CameraSrtLiveStreamer.kt +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.srt.streamers - -import android.content.Context -import io.github.thibaultbee.streampack.data.BitrateRegulatorConfig -import io.github.thibaultbee.streampack.ext.srt.data.SrtConnectionDescriptor -import io.github.thibaultbee.streampack.ext.srt.internal.endpoints.sinks.SrtSink -import io.github.thibaultbee.streampack.ext.srt.regulator.srt.SrtBitrateRegulator -import io.github.thibaultbee.streampack.ext.srt.streamers.interfaces.ISrtLiveStreamer -import io.github.thibaultbee.streampack.internal.endpoints.composites.ConnectableCompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.utils.Scheduler -import io.github.thibaultbee.streampack.internal.utils.extensions.defaultTsServiceInfo -import io.github.thibaultbee.streampack.listeners.OnConnectionListener -import io.github.thibaultbee.streampack.listeners.OnErrorListener -import io.github.thibaultbee.streampack.regulator.IBitrateRegulatorFactory -import io.github.thibaultbee.streampack.streamers.bases.BaseCameraStreamer -import io.github.thibaultbee.streampack.streamers.live.BaseCameraLiveStreamer - -/** - * [BaseCameraStreamer] that sends microphones and camerao frames to a remote Secure Reliable - * Transport (SRT) device. - * - * @param context application context - * @param tsServiceInfo MPEG-TS service description - * @param enableAudio [Boolean.true] to capture audio. False to disable audio capture. - * @param bitrateRegulatorFactory a [IBitrateRegulatorFactory] implementation. Use it to customized bitrate regulator. If bitrateRegulatorConfig is not null, bitrateRegulatorFactory must not be null. - * @param bitrateRegulatorConfig bitrate regulator configuration. If bitrateRegulatorFactory is not null, bitrateRegulatorConfig must not be null. - */ -class CameraSrtLiveStreamer( - context: Context, - enableAudio: Boolean = true, - tsServiceInfo: TsServiceInfo = context.defaultTsServiceInfo, - bitrateRegulatorFactory: IBitrateRegulatorFactory? = null, - bitrateRegulatorConfig: BitrateRegulatorConfig? = null -) : BaseCameraLiveStreamer( - context = context, - enableAudio = enableAudio, - internalEndpoint = ConnectableCompositeEndpoint( - TSMuxer().apply { addService(tsServiceInfo) }, - SrtSink() - ) -), - ISrtLiveStreamer { - - /** - * Bitrate regulator. Calls regularly by [scheduler]. Don't call it otherwise or you might break regulation. - */ - private val bitrateRegulator = bitrateRegulatorConfig?.let { config -> - bitrateRegulatorFactory?.newBitrateRegulator( - config, - { - val videoEncoder = videoEncoder - ?: throw UnsupportedOperationException("Bitrate regulator set without a video encoder") - videoEncoder.bitrate = it - }, - { /* Do nothing for audio */ } - ) as SrtBitrateRegulator - } - - /** - * Scheduler for bitrate regulation - */ - private val scheduler = Scheduler(500) { - val videoEncoder = videoEncoder - ?: throw UnsupportedOperationException("Scheduler runs but no video encoder set") - bitrateRegulator?.update( - srtProducer.stats, - videoEncoder.bitrate, - audioEncoder?.bitrate ?: 0 - ) - ?: throw UnsupportedOperationException("Scheduler runs but no bitrate regulator set") - } - - private val srtProducer = (internalEndpoint as ConnectableCompositeEndpoint).sink as SrtSink - - /** - * Get/set SRT stream ID. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#srto_streamid) - */ - override var streamId: String - /** - * Get SRT stream ID - * @return stream ID - */ - get() = srtProducer.streamId - /** - * @param value stream ID - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - set(value) { - srtProducer.streamId = value - } - - /** - * Get/set SRT passphrase. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#srto_passphrase) - */ - override var passPhrase: String - /** - * Get SRT passphrase - * @return passphrase - */ - get() = srtProducer.passPhrase - /** - * @param value passphrase - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - set(value) { - srtProducer.passPhrase = value - } - - /** - * Get/set bidirectional latency in milliseconds. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#SRTO_LATENCY) - */ - override val latency: Int - /** - * Get latency in milliseconds - * @return latency - */ - get() = srtProducer.latency - - /** - * Connect to an SRT server with correct Live streaming parameters. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param ip server ip - * @param port server port - * @throws Exception if connection has failed or configuration has failed - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - override suspend fun connect(ip: String, port: Int) { - val connection = SrtConnectionDescriptor(ip, port) - srtProducer.connect(connection) - } - - /** - * Connect to an SRT server with correct Live streaming parameters. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param connection the SRT connection - * @throws Exception if connection has failed or configuration has failed - */ - override suspend fun connect(connection: SrtConnectionDescriptor) { - srtProducer.connect(connection) - } - - /** - * Same as [BaseCameraLiveStreamer.startStream] but also starts bitrate regulator. - */ - override suspend fun startStream() { - super.startStream() - if (bitrateRegulator != null) { - scheduler.start() - } - } - - /** - * Same as [BaseCameraLiveStreamer.startStream] but also starts bitrate regulator. - */ - override suspend fun startStream(url: String) { - super.startStream(url) - if (bitrateRegulator != null) { - scheduler.start() - } - } - - /** - * Connect to an SRT server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param ip server ip - * @param port server port - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - @Deprecated( - "Use the new startStream(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("startStream(SrtConnectionDescriptor)") - ) - override suspend fun startStream(ip: String, port: Int) { - val connection = SrtConnectionDescriptor(ip, port) - startStream(connection) - } - - /** - * Connect to an SRT server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param connection the SRT connection - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - override suspend fun startStream(connection: SrtConnectionDescriptor) { - connect(connection) - startStream() - } - - /** - * Same as [BaseCameraLiveStreamer.stopStream] but also stops bitrate regulator. - */ - override suspend fun stopStream() { - scheduler.cancel() - super.stopStream() - } -} diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/ScreenRecorderSrtLiveStreamer.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/ScreenRecorderSrtLiveStreamer.kt deleted file mode 100644 index 927959b78..000000000 --- a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/ScreenRecorderSrtLiveStreamer.kt +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.srt.streamers - -import android.app.Service -import android.content.Context -import io.github.thibaultbee.streampack.data.BitrateRegulatorConfig -import io.github.thibaultbee.streampack.ext.srt.data.SrtConnectionDescriptor -import io.github.thibaultbee.streampack.ext.srt.internal.endpoints.sinks.SrtSink -import io.github.thibaultbee.streampack.ext.srt.regulator.srt.SrtBitrateRegulator -import io.github.thibaultbee.streampack.ext.srt.services.ScreenRecorderSrtLiveService -import io.github.thibaultbee.streampack.ext.srt.streamers.interfaces.ISrtLiveStreamer -import io.github.thibaultbee.streampack.internal.endpoints.composites.ConnectableCompositeEndpoint -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.TSMuxer -import io.github.thibaultbee.streampack.internal.endpoints.muxers.ts.data.TsServiceInfo -import io.github.thibaultbee.streampack.internal.utils.Scheduler -import io.github.thibaultbee.streampack.internal.utils.extensions.defaultTsServiceInfo -import io.github.thibaultbee.streampack.regulator.IBitrateRegulatorFactory -import io.github.thibaultbee.streampack.streamers.bases.BaseScreenRecorderStreamer -import io.github.thibaultbee.streampack.streamers.live.BaseScreenRecorderLiveStreamer - -/** - * [BaseScreenRecorderStreamer] that sends microphone and screen frames to a remote Secure Reliable - * Transport (SRT) device. - * To run this streamer while application is on background, you have to extend a [Service]. - * To simplify the integration, a service is provided in [ScreenRecorderSrtLiveService]. - * - * As an example, see `demo-screenrecorder`. - * - * @param context application context - * @param enableAudio [Boolean.true] to also capture audio. False to disable audio capture. - * @param tsServiceInfo MPEG-TS service description - * @param bitrateRegulatorFactory a [IBitrateRegulatorFactory] implementation. Use it to customized bitrate regulator. If bitrateRegulatorConfig is not null, bitrateRegulatorFactory must not be null. - * @param bitrateRegulatorConfig bitrate regulator configuration. If bitrateRegulatorFactory is not null, bitrateRegulatorConfig must not be null. - */ -class ScreenRecorderSrtLiveStreamer( - context: Context, - enableAudio: Boolean = true, - tsServiceInfo: TsServiceInfo = context.defaultTsServiceInfo, - bitrateRegulatorFactory: IBitrateRegulatorFactory? = null, - bitrateRegulatorConfig: BitrateRegulatorConfig? = null -) : BaseScreenRecorderLiveStreamer( - context = context, - enableAudio = enableAudio, - internalEndpoint = ConnectableCompositeEndpoint( - TSMuxer().apply { addService(tsServiceInfo) }, - SrtSink() - ) -), - ISrtLiveStreamer { - - /** - * Bitrate regulator. Calls regularly by [scheduler]. Don't call it otherwise or you might break regulation. - */ - private val bitrateRegulator = bitrateRegulatorConfig?.let { config -> - bitrateRegulatorFactory?.newBitrateRegulator( - config, - { - val videoEncoder = videoEncoder - ?: throw UnsupportedOperationException("Bitrate regulator set without a video encoder") - videoEncoder.bitrate = it - }, - { /* Do nothing for audio */ } - ) as SrtBitrateRegulator - } - - /** - * Scheduler for bitrate regulation - */ - private val scheduler = Scheduler(500) { - val videoEncoder = videoEncoder - ?: throw UnsupportedOperationException("Scheduler runs but no video encoder set") - bitrateRegulator?.update( - srtProducer.stats, - videoEncoder.bitrate, - audioEncoder?.bitrate ?: 0 - ) - ?: throw UnsupportedOperationException("Scheduler runs but no bitrate regulator set") - } - - private val srtProducer = (internalEndpoint as ConnectableCompositeEndpoint).sink as SrtSink - - /** - * Get/set SRT stream ID. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#srto_streamid) - */ - override var streamId: String - /** - * Get SRT stream ID - * @return stream ID - */ - get() = srtProducer.streamId - /** - * @param value stream ID - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - set(value) { - srtProducer.streamId = value - } - - /** - * Get/set SRT passphrase. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#srto_passphrase) - */ - override var passPhrase: String - /** - * Get SRT passphrase - * @return passphrase - */ - get() = srtProducer.passPhrase - /** - * @param value passphrase - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - set(value) { - srtProducer.passPhrase = value - } - - /** - * Get/set bidirectional latency in milliseconds. - * **See:** [SRT Socket Options](https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#SRTO_LATENCY) - */ - override val latency: Int - /** - * Get latency in milliseconds - * @return latency - */ - get() = srtProducer.latency - - /** - * Connect to an SRT server with correct Live streaming parameters. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param ip server ip - * @param port server port - * @throws Exception if connection has failed or configuration has failed - */ - @Deprecated( - "Use the new connect(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - override suspend fun connect(ip: String, port: Int) { - val connection = SrtConnectionDescriptor(ip, port) - srtProducer.connect(connection) - } - - /** - * Connect to an SRT server with correct Live streaming parameters. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param connection the SRT connection - * @throws Exception if connection has failed or configuration has failed - */ - override suspend fun connect(connection: SrtConnectionDescriptor) { - srtProducer.connect(connection) - } - - /** - * Same as [BaseScreenRecorderLiveStreamer.startStream] but also starts bitrate regulator. - */ - override suspend fun startStream() { - super.startStream() - if (bitrateRegulator != null) { - scheduler.start() - } - } - - /** - * Same as [BaseScreenRecorderLiveStreamer.startStream] but also starts bitrate regulator. - */ - override suspend fun startStream(url: String) { - super.startStream(url) - if (bitrateRegulator != null) { - scheduler.start() - } - } - - /** - * Connect to an SRT server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param ip server ip - * @param port server port - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - @Deprecated( - "Use the new startStream(SrtConnectionDescriptor) method", - replaceWith = ReplaceWith("startStream(SrtConnectionDescriptor)") - ) - override suspend fun startStream(ip: String, port: Int) { - val connection = SrtConnectionDescriptor(ip, port) - startStream(connection) - } - - /** - * Connect to an SRT server and start stream. - * Same as calling [connect], then [startStream]. - * To avoid creating an unresponsive UI, do not call on main thread. - * - * @param connection the SRT connection - * @throws Exception if connection has failed or configuration has failed or [startStream] has failed too. - */ - override suspend fun startStream(connection: SrtConnectionDescriptor) { - connect(connection) - startStream() - } - - /** - * Same as [BaseScreenRecorderLiveStreamer.stopStream] but also stops bitrate regulator. - */ - override suspend fun stopStream() { - scheduler.cancel() - super.stopStream() - } -} \ No newline at end of file diff --git a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/interfaces/ISrtLiveStreamer.kt b/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/interfaces/ISrtLiveStreamer.kt deleted file mode 100644 index 4c4cbbc7f..000000000 --- a/extensions/srt/src/main/java/io/github/thibaultbee/streampack/ext/srt/streamers/interfaces/ISrtLiveStreamer.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2021 Thibault B. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.github.thibaultbee.streampack.ext.srt.streamers.interfaces - -import io.github.thibaultbee.streampack.ext.srt.data.SrtConnectionDescriptor -import io.github.thibaultbee.streampack.streamers.interfaces.ILiveStreamer - -interface ISrtLiveStreamer : ILiveStreamer { - /** - * Get/set connection passphrase. - */ - var passPhrase: String - - /** - * Get/set stream id. - */ - var streamId: String - - /** - * Get/set bidirectional latency in milliseconds. - */ - val latency: Int - - /** - * Connect to a remote server. - * - * @param ip server ip - * @param port server port - * @throws Exception if connection has failed or configuration has failed - */ - @Deprecated( - "Use connect(SrtConnectionDescriptor) instead", - replaceWith = ReplaceWith("connect(SrtConnectionDescriptor)") - ) - suspend fun connect(ip: String, port: Int) - - /** - * Connect to a remote server. - * - * @param connection the SRT connection - * @throws Exception if connection has failed or configuration has failed - */ - suspend fun connect(connection: SrtConnectionDescriptor) - - /** - * Same as [connect] then [startStream]. - * - * @param ip server ip - * @param port server port - * @throws Exception if connection has failed or configuration has failed or startStream failed. - */ - @Deprecated( - "Use startStream(SrtConnectionDescriptor) instead", - replaceWith = ReplaceWith("startStream(SrtConnectionDescriptor)") - ) - suspend fun startStream(ip: String, port: Int) - - /** - * Same as [connect] then [startStream]. - * - * @param connection the SRT connection - * @throws Exception if connection has failed or configuration has failed or startStream failed. - */ - suspend fun startStream(connection: SrtConnectionDescriptor) -} \ No newline at end of file diff --git a/services/.gitignore b/services/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/services/.gitignore @@ -0,0 +1 @@ +/build diff --git a/services/build.gradle b/services/build.gradle new file mode 100644 index 000000000..b828aedae --- /dev/null +++ b/services/build.gradle @@ -0,0 +1,19 @@ +apply from: "${project.rootDir}/common_library.gradle" +apply from: "${project.rootDir}/publish.gradle" + +android { + namespace 'io.github.thibaultbee.streampack.services' +} +ext { + artifactName = 'streampack-services' + artifactDescription = 'Services components for StreamPack.' +} + +dependencies { + implementation project(':core') + + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" + implementation 'androidx.appcompat:appcompat:1.6.1' + + api 'androidx.lifecycle:lifecycle-service:2.8.0' +} diff --git a/services/proguard-rules.pro b/services/proguard-rules.pro new file mode 100644 index 000000000..f1b424510 --- /dev/null +++ b/services/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/services/src/main/AndroidManifest.xml b/services/src/main/AndroidManifest.xml new file mode 100644 index 000000000..4e0939c8c --- /dev/null +++ b/services/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/core/src/main/java/io/github/thibaultbee/streampack/streamers/services/BaseScreenRecorderService.kt b/services/src/main/java/io/github/thibaultbee/streampack/services/DefaultScreenRecorderService.kt similarity index 63% rename from core/src/main/java/io/github/thibaultbee/streampack/streamers/services/BaseScreenRecorderService.kt rename to services/src/main/java/io/github/thibaultbee/streampack/services/DefaultScreenRecorderService.kt index 7ad679ebf..c697c00cc 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/streamers/services/BaseScreenRecorderService.kt +++ b/services/src/main/java/io/github/thibaultbee/streampack/services/DefaultScreenRecorderService.kt @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.streamers.services +package io.github.thibaultbee.streampack.services import android.Manifest import android.app.Notification -import android.app.Service import android.content.ComponentName import android.content.Context import android.content.Intent @@ -29,15 +28,14 @@ import android.os.IBinder import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.app.ActivityCompat +import androidx.lifecycle.LifecycleService +import androidx.lifecycle.lifecycleScope import io.github.thibaultbee.streampack.R import io.github.thibaultbee.streampack.internal.utils.extensions.rootCause -import io.github.thibaultbee.streampack.listeners.OnConnectionListener -import io.github.thibaultbee.streampack.listeners.OnErrorListener import io.github.thibaultbee.streampack.logger.Logger -import io.github.thibaultbee.streampack.streamers.bases.BaseScreenRecorderStreamer -import io.github.thibaultbee.streampack.streamers.interfaces.ILiveStreamer -import io.github.thibaultbee.streampack.utils.NotificationUtils -import io.github.thibaultbee.streampack.utils.getStreamer +import io.github.thibaultbee.streampack.services.utils.NotificationUtils +import io.github.thibaultbee.streampack.streamers.DefaultScreenRecorderStreamer +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking /** @@ -58,7 +56,7 @@ import kotlinx.coroutines.runBlocking * - R.string.service_notification_* string values * - override open onNotification methods: [onConnectionSuccessNotification], [onConnectionLostNotification], [onConnectionFailedNotification] and [onErrorNotification] * - * If you want to keep the notification, you shall not override [BaseScreenRecorderStreamer.onErrorListener] and [ILiveStreamer.onConnectionListener]. + * If you want to keep the notification, you shall not override [DefaultScreenRecorderStreamer.onErrorListener] and [ILiveStreamer.onConnectionListener]. * * @param notificationId the notification id a unique number * @param channelId the notification channel id @@ -66,23 +64,20 @@ import kotlinx.coroutines.runBlocking * @param channelDescriptionResourceId A string resource identifier for the user visible description of the notification channel. * @param notificationIconResourceId A drawable resource identifier for the user visible icon of the notification channel. */ -abstract class BaseScreenRecorderService( +abstract class DefaultScreenRecorderService( private val notificationId: Int = DEFAULT_NOTIFICATION_ID, protected val channelId: String = DEFAULT_NOTIFICATION_CHANNEL_ID, @StringRes protected val channelNameResourceId: Int = R.string.default_channel_name, @StringRes protected val channelDescriptionResourceId: Int = 0, @DrawableRes protected val notificationIconResourceId: Int = R.drawable.ic_baseline_linked_camera_24 -) : Service() { - protected var streamer: BaseScreenRecorderStreamer? = null +) : LifecycleService() { + protected var streamer: DefaultScreenRecorderStreamer? = null private val binder = ScreenRecorderServiceBinder() private val notificationUtils: NotificationUtils by lazy { NotificationUtils(this, channelId, notificationId) } private var hasNotified = false - private val liveStreamer: ILiveStreamer? - get() = streamer?.getStreamer() - override fun onCreate() { super.onCreate() @@ -93,50 +88,38 @@ abstract class BaseScreenRecorderService( } override fun onBind(intent: Intent): IBinder? { + super.onBind(intent) + try { - val constructorBundle = intent.extras?.getBundle(CONSTRUCTOR_BUNDLE_KEY) + val customBundle = intent.extras?.getBundle(CUSTOM_BUNDLE_KEY) ?: throw IllegalStateException("Config bundle must be pass to the service") - val enableAudio = constructorBundle.getBoolean(ENABLE_AUDIO_KEY) - if (enableAudio) { - if (ActivityCompat.checkSelfPermission( - this, - Manifest.permission.RECORD_AUDIO - ) != PackageManager.PERMISSION_GRANTED - ) { - throw SecurityException("Permission RECORD_AUDIO must have been granted!") - } - } - - streamer = createStreamer(constructorBundle) - - streamer?.onErrorListener = object : OnErrorListener { - override fun onError(e: Exception) { - Logger.e(TAG, "An error occurred", e) - onErrorNotification(e)?.let { notify(it) } - stopSelf() - } - } - - liveStreamer?.onConnectionListener = - object : OnConnectionListener { - override fun onLost(message: String) { - Logger.e(TAG, "Connection lost: $message") - onConnectionLostNotification(message)?.let { notify(it) } - stopSelf() - } + streamer = createStreamer(customBundle) - override fun onFailed(message: String) { - Logger.e(TAG, "Connection failed: $message") - onConnectionFailedNotification(message)?.let { notify(it) } - stopSelf() + streamer?.let { + lifecycleScope.launch { + it.exception.collect { e -> + if (e != null) { + Logger.e(TAG, "An error occurred", e) + onErrorNotification(e)?.let { notify(it) } + stopSelf() + } } - - override fun onSuccess() { - Logger.i(TAG, "Connection succeeded") - onConnectionSuccessNotification()?.let { notify(it) } + } + lifecycleScope.launch { + it.isOpened.collect { isOpened -> + if (isOpened) { + Logger.i(TAG, "Connection succeeded") + onConnectionSuccessNotification()?.let { notify(it) } + } else { + val message = "TMP" // TODO + Logger.e(TAG, "Connection lost: $message") + onConnectionLostNotification(message)?.let { notify(it) } + stopSelf() + } } } + } } catch (e: Exception) { Logger.e(TAG, "An error occurred", e) onErrorNotification(e)?.let { notify(it) } @@ -148,17 +131,32 @@ abstract class BaseScreenRecorderService( /** * Calls when service needs to create the streamer. + * You can customize the streamer by overriding this method. * + * @param bundle the custom bundle passed as [launch] parameter. * @return the streamer to use. */ - protected abstract fun createStreamer(bundle: Bundle): BaseScreenRecorderStreamer + open fun createStreamer(bundle: Bundle): DefaultScreenRecorderStreamer { + if (ActivityCompat.checkSelfPermission( + this, + Manifest.permission.RECORD_AUDIO + ) != PackageManager.PERMISSION_GRANTED + ) { + throw SecurityException("Permission RECORD_AUDIO must have been granted!") + } + + return DefaultScreenRecorderStreamer( + applicationContext, + enableMicrophone = true, + ) + } override fun onDestroy() { super.onDestroy() runBlocking { streamer?.stopStream() + streamer?.close() } - (streamer as ILiveStreamer?)?.disconnect() streamer?.release() streamer = null } @@ -239,66 +237,38 @@ abstract class BaseScreenRecorderService( } protected inner class ScreenRecorderServiceBinder : Binder() { - val streamer: BaseScreenRecorderStreamer? - get() = this@BaseScreenRecorderService.streamer + val streamer: DefaultScreenRecorderStreamer? + get() = this@DefaultScreenRecorderService.streamer } companion object { - private const val TAG = "BaseScreenRecorderService" + private const val TAG = "DefaultScreenRecorderService" const val DEFAULT_NOTIFICATION_CHANNEL_ID = "io.github.thibaultbee.streampack.streamers.services" const val DEFAULT_NOTIFICATION_ID = 3782 - private const val CONSTRUCTOR_BUNDLE_KEY = "config" - const val ENABLE_AUDIO_KEY = "enableAudio" - const val MUXER_CONFIG_KEY = "muxerConfig" - const val ENDPOINT_CONFIG_KEY = "endpointConfig" - - /** - * Starts and binds the service with the appropriate parameters. - * - * @param context The application context. - * @param serviceClass The service class to launch. It is a children of [BaseScreenRecorderService]. - * @param enableAudio enable or disable audio. - * @param onServiceCreated Callback that returns a children of [BaseScreenRecorderService] instance when the service has been connected. - * @param onServiceDisconnected Callback that will be called when the service is disconnected. - */ - fun launch( - context: Context, - serviceClass: Class, - enableAudio: Boolean, - onServiceCreated: (BaseScreenRecorderStreamer) -> Unit, - onServiceDisconnected: (name: ComponentName?) -> Unit - ) { - launch( - context, - serviceClass, - Bundle().apply { putBoolean(ENABLE_AUDIO_KEY, enableAudio) }, - onServiceCreated, - onServiceDisconnected - ) - } + private const val CUSTOM_BUNDLE_KEY = "bundle" /** * Starts and binds the service with the appropriate parameters. * * @param context The application context. - * @param serviceClass The service class to launch. It is a children of [BaseScreenRecorderService]. - * @param constructorBundle the streamer constructor configuration [Bundle]. - * @param onServiceCreated Callback that returns a children of [BaseScreenRecorderService] instance when the service has been connected. + * @param serviceClass The service class to launch. It is a children of [DefaultScreenRecorderService]. + * @param customBundle the user defined [Bundle]. + * @param onServiceCreated Callback that returns a children of [DefaultScreenRecorderService] instance when the service has been connected. * @param onServiceDisconnected Callback that will be called when the service is disconnected. */ fun launch( context: Context, - serviceClass: Class, - constructorBundle: Bundle, - onServiceCreated: (BaseScreenRecorderStreamer) -> Unit, + serviceClass: Class, + customBundle: Bundle, + onServiceCreated: (DefaultScreenRecorderStreamer) -> Unit, onServiceDisconnected: (name: ComponentName?) -> Unit ) { val connection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder) { - if (service is BaseScreenRecorderService.ScreenRecorderServiceBinder) { + if (service is ScreenRecorderServiceBinder) { service.streamer?.let { onServiceCreated(it) } } } @@ -309,7 +279,7 @@ abstract class BaseScreenRecorderService( } val intent = Intent(context, serviceClass).apply { - putExtra(CONSTRUCTOR_BUNDLE_KEY, constructorBundle) + putExtra(CUSTOM_BUNDLE_KEY, customBundle) } context.bindService( diff --git a/core/src/main/java/io/github/thibaultbee/streampack/utils/NotificationUtils.kt b/services/src/main/java/io/github/thibaultbee/streampack/services/utils/NotificationUtils.kt similarity index 98% rename from core/src/main/java/io/github/thibaultbee/streampack/utils/NotificationUtils.kt rename to services/src/main/java/io/github/thibaultbee/streampack/services/utils/NotificationUtils.kt index 63026a268..3b47b0715 100644 --- a/core/src/main/java/io/github/thibaultbee/streampack/utils/NotificationUtils.kt +++ b/services/src/main/java/io/github/thibaultbee/streampack/services/utils/NotificationUtils.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.github.thibaultbee.streampack.utils +package io.github.thibaultbee.streampack.services.utils import android.app.Notification import android.app.NotificationChannel diff --git a/services/src/main/res/values/attrs.xml b/services/src/main/res/values/attrs.xml new file mode 100644 index 000000000..dafde487c --- /dev/null +++ b/services/src/main/res/values/attrs.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/src/main/java/io/github/thibaultbee/streampack/ui/views/PreviewView.kt b/ui/src/main/java/io/github/thibaultbee/streampack/ui/views/PreviewView.kt index 08fd5962c..4a30333e0 100644 --- a/ui/src/main/java/io/github/thibaultbee/streampack/ui/views/PreviewView.kt +++ b/ui/src/main/java/io/github/thibaultbee/streampack/ui/views/PreviewView.kt @@ -37,9 +37,9 @@ import androidx.camera.viewfinder.surface.populateFromCharacteristics import androidx.core.app.ActivityCompat import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.lifecycleScope -import io.github.thibaultbee.streampack.ui.R import io.github.thibaultbee.streampack.logger.Logger import io.github.thibaultbee.streampack.streamers.interfaces.ICameraStreamer +import io.github.thibaultbee.streampack.ui.R import io.github.thibaultbee.streampack.utils.OrientationUtils import io.github.thibaultbee.streampack.utils.getCameraCharacteristics import kotlinx.coroutines.CoroutineScope @@ -209,7 +209,7 @@ class PreviewView @JvmOverloads constructor( val x = touchUpEvent?.x ?: (width / 2f) val y = touchUpEvent?.y ?: (height / 2f) try { - it.settings.camera.focusMetering.onTap( + it.videoSource.settings.focusMetering.onTap( PointF(x, y), Rect(this.x.toInt(), this.y.toInt(), width, height), OrientationUtils.getSurfaceOrientationDegrees(display.rotation) @@ -406,7 +406,7 @@ class PreviewView @JvmOverloads constructor( private inner class PinchToZoomOnScaleGestureListener : SimpleOnScaleGestureListener() { override fun onScale(detector: ScaleGestureDetector): Boolean { - streamer?.settings?.camera?.zoom?.let { + streamer?.videoSource?.settings?.zoom?.let { it.onPinch(detector.scaleFactor) listener?.onZoomRationOnPinchChanged(it.zoomRatio) }