Skip to content

Commit 71b2747

Browse files
committed
Fix bug in decoding & color formats
1 parent 7f7ea46 commit 71b2747

File tree

8 files changed

+207
-293
lines changed

8 files changed

+207
-293
lines changed

README.md

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Unlike [AndroidX Media ExoPlayer](https://github.com/androidx/media) which also
1616
- Audio AAC LC only.
1717
- Basic/Digest authentication.
1818
- Supports majority of RTSP IP cameras.
19-
- Auto Decode raw frames to Media Image & YUV ByteArray & NV21 ByteArray & Bitmap.
20-
- Using [renderscript-intrinsics-replacement-toolkit](https://github.com/android/renderscript-intrinsics-replacement-toolkit) for NV21 to Bitmap decoding.
19+
- Auto Decode raw frames to Media Image & YUV ByteArray & Bitmap.
20+
- Using [renderscript-intrinsics-replacement-toolkit](https://github.com/android/renderscript-intrinsics-replacement-toolkit) for YUV to Bitmap decoding.
2121

2222
## Permissions
2323

@@ -127,7 +127,7 @@ rtsp.setFrameListener(object : RtspFrameListener {
127127
override fun onVideoNalUnitReceived(frame: Frame?) {
128128
// Send raw H264 NAL unit to your custom decoder
129129
}
130-
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuv420Bytes: ByteArray?, bitmap: Bitmap?) {}
130+
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuvBytes: ByteArray?, bitmap: Bitmap?) {}
131131
override fun onAudioSampleReceived(frame: Frame?) {
132132
// Send raw audio to decoder
133133
}
@@ -148,7 +148,7 @@ You can still use library with H264 to YUV MediaImage decoding.
148148
// ... build rtsp
149149
rtsp.setFrameListener(object : RtspFrameListener {
150150
override fun onVideoNalUnitReceived(frame: Frame?) {}
151-
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuv420Bytes: ByteArray?, bitmap: Bitmap?) {
151+
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuvBytes: ByteArray?, bitmap: Bitmap?) {
152152
// Notice: you should use mediaImage object sync on this thread
153153
}
154154
override fun onAudioSampleReceived(frame: Frame?) {
@@ -166,14 +166,14 @@ rtsp.stop()
166166

167167
### 5) YUV byte array
168168

169-
You can still use library with H264 to YUV420 ByteArray decoding.
169+
You can still use library with H264 to YUV ByteArray decoding.
170170

171171
```kotlin
172172
// ... build rtsp
173173
rtsp.setFrameListener(object : RtspFrameListener {
174174
override fun onVideoNalUnitReceived(frame: Frame?) {}
175-
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuv420Bytes: ByteArray?, bitmap: Bitmap?) {
176-
// you can decode YUV420 to Bitmap by your custom decoder
175+
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuvBytes: ByteArray?, bitmap: Bitmap?) {
176+
// you can decode YUV to Bitmap by your custom decoder
177177
}
178178
override fun onAudioSampleReceived(frame: Frame?) {
179179
// Send raw audio to decoder
@@ -188,39 +188,15 @@ rtsp.stop()
188188

189189
---
190190

191-
### 6) NV21 byte array
192-
193-
You can still use library with H264 to NV21 ByteArray decoding.
194-
195-
```kotlin
196-
// ... build rtsp
197-
rtsp.setFrameListener(object : RtspFrameListener {
198-
override fun onVideoNalUnitReceived(frame: Frame?) {}
199-
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuv420Bytes: ByteArray?, bitmap: Bitmap?) {
200-
// you can decode NV21 to Bitmap by your custom decoder
201-
}
202-
override fun onAudioSampleReceived(frame: Frame?) {
203-
// Send raw audio to decoder
204-
}
205-
})
206-
rtsp.setRequestAudioSample(true)
207-
rtsp.setRequestNv21Bytes(true)
208-
rtsp.start(playVideo = true, playAudio = true)
209-
// ...
210-
rtsp.stop()
211-
```
212-
213-
---
214-
215-
### 7) Bitmap
191+
### 6) Bitmap
216192

217193
You can still use library with H264 to Bitmap decoding.
218194

219195
```kotlin
220196
// ... build rtsp
221197
rtsp.setFrameListener(object : RtspFrameListener {
222198
override fun onVideoNalUnitReceived(frame: Frame?) {}
223-
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuv420Bytes: ByteArray?, bitmap: Bitmap?) {
199+
override fun onVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuvBytes: ByteArray?, bitmap: Bitmap?) {
224200
// Use the bitmap
225201
}
226202
override fun onAudioSampleReceived(frame: Frame?) {

app/src/main/java/ir/am3n/rtsp.client.demo/LiveFragment.kt

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
package ir.am3n.rtsp.client.demo
22

33
import android.annotation.SuppressLint
4-
import android.graphics.*
4+
import android.graphics.Bitmap
55
import android.media.Image
66
import android.os.Bundle
77
import android.text.Editable
88
import android.text.TextWatcher
99
import android.util.Log
10-
import android.view.*
10+
import android.view.LayoutInflater
11+
import android.view.View
12+
import android.view.ViewGroup
1113
import android.widget.Toast
12-
import androidx.core.net.toUri
1314
import androidx.fragment.app.Fragment
1415
import androidx.lifecycle.ViewModelProvider
1516
import ir.am3n.rtsp.client.Rtsp
16-
import ir.am3n.rtsp.client.interfaces.Frame
1717
import ir.am3n.rtsp.client.data.SdpInfo
1818
import ir.am3n.rtsp.client.demo.databinding.FragmentLiveBinding
19+
import ir.am3n.rtsp.client.interfaces.Frame
1920
import ir.am3n.rtsp.client.interfaces.RtspFrameListener
2021
import ir.am3n.rtsp.client.interfaces.RtspStatusListener
2122
import kotlinx.coroutines.CoroutineScope
2223
import kotlinx.coroutines.Dispatchers
2324
import kotlinx.coroutines.delay
2425
import kotlinx.coroutines.launch
25-
import java.lang.Thread.sleep
26-
import kotlin.concurrent.thread
2726

2827
@SuppressLint("SetTextI18n")
2928
class LiveFragment : Fragment() {
@@ -131,9 +130,9 @@ class LiveFragment : Fragment() {
131130

132131
override fun onVideoFrameReceived(
133132
width: Int, height: Int, mediaImage: Image?,
134-
yuv420Bytes: ByteArray?, nv21Bytes: ByteArray?, bitmap: Bitmap?
133+
yuvBytes: ByteArray?, bitmap: Bitmap?
135134
) {
136-
Log.d(TAG, "onVideoFrameReceived() img: $mediaImage yuv: $yuv420Bytes nv21: $nv21Bytes bmp: $bitmap")
135+
Log.d(TAG, "onVideoFrameReceived() img: $mediaImage yuv: $yuvBytes bmp: $bitmap")
137136
binding.img.run {
138137
post { setImageBitmap(bitmap) }
139138
}
@@ -181,14 +180,11 @@ class LiveFragment : Fragment() {
181180
rtsp.stop()
182181
} else {
183182

184-
binding.rsv.init(liveViewModel.rtspRequest.value!!.toUri())
185-
binding.rsv.start(playVideo = true, playAudio = true)
183+
//binding.rsv.init(liveViewModel.rtspRequest.value!!.toUri())
184+
//binding.rsv.start(playVideo = true, playAudio = true)
186185

187-
thread {
188-
sleep(2000)
189-
rtsp.init(liveViewModel.rtspRequest.value!!, timeout = 2_000)
190-
rtsp.start(playVideo = true, playAudio = true)
191-
}
186+
rtsp.init(liveViewModel.rtspRequest.value!!, timeout = 2_000)
187+
rtsp.start(playVideo = true, playAudio = false)
192188

193189
}
194190
}
@@ -198,11 +194,10 @@ class LiveFragment : Fragment() {
198194

199195
rtsp.setSurfaceView(binding.svVideo)
200196

201-
//rtsp.setRequestMediaImage(true)
202-
//rtsp.setRequestYuvBytes(true)
203-
//rtsp.setRequestNv21Bytes(true)
204-
//rtsp.setRequestBitmap(true)
205-
//rtsp.setRequestAudioSample(true)
197+
rtsp.setRequestMediaImage(true)
198+
rtsp.setRequestYuvBytes(true)
199+
rtsp.setRequestBitmap(true)
200+
rtsp.setRequestAudioSample(true)
206201

207202
return binding.root
208203
}
@@ -211,6 +206,7 @@ class LiveFragment : Fragment() {
211206
super.onResume()
212207
if (Rtsp.DEBUG) Log.v(TAG, "onResume()")
213208
liveViewModel.loadParams(requireContext())
209+
binding.bnStartStop.performClick()
214210
}
215211

216212
override fun onPause() {

rtsp-client/build.gradle

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ plugins {
44
}
55

66
android {
7+
78
namespace 'ir.am3n.rtsp.client'
8-
compileSdkVersion 34
9+
10+
compileSdk 34
11+
912
defaultConfig {
10-
minSdkVersion 23
11-
targetSdkVersion 34
13+
minSdk 23
14+
targetSdk 34
1215
multiDexEnabled true
1316
}
1417

@@ -27,5 +30,5 @@ dependencies {
2730
implementation "androidx.annotation:annotation:1.5.0"
2831
implementation "com.google.android.exoplayer:exoplayer-core:2.18.3"
2932
implementation "androidx.media3:media3-exoplayer:1.4.1"
30-
implementation 'com.github.am3n:renderscript-toolkit:'
33+
api "com.github.am3n:renderscript-intrinsics-replacement-toolkit:1.0.0"
3134
}

rtsp-client/src/main/java/ir/am3n/rtsp/client/Rtsp.kt

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class Rtsp {
7474
}
7575
override fun onVideoFrameReceived(
7676
width: Int, height: Int, mediaImage: Image?,
77-
yuv420Bytes: ByteArray?, nv21Bytes: ByteArray?, bitmap: Bitmap?
77+
yuvBytes: ByteArray?, bitmap: Bitmap?
7878
) {}
7979
override fun onAudioSampleReceived(frame: Frame?) {}
8080
})
@@ -139,7 +139,6 @@ class Rtsp {
139139
private var playVideo = true
140140
private var requestMediaImage = false
141141
private var requestYuvBytes = false
142-
private var requestNv21Bytes = false
143142
private var requestBitmap = false
144143

145144
private var playAudio = true
@@ -226,8 +225,8 @@ class Rtsp {
226225
}
227226
}
228227

229-
override fun onRtspVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuv420Bytes: ByteArray?, nv21Bytes: ByteArray?, bitmap: Bitmap?) {
230-
frameListener?.onVideoFrameReceived(width, height, mediaImage, yuv420Bytes, nv21Bytes, bitmap)
228+
override fun onRtspVideoFrameReceived(width: Int, height: Int, mediaImage: Image?, yuvBytes: ByteArray?, bitmap: Bitmap?) {
229+
frameListener?.onVideoFrameReceived(width, height, mediaImage, yuvBytes, bitmap)
231230
}
232231

233232
override fun onRtspAudioSampleReceived(data: ByteArray, offset: Int, length: Int, timestamp: Long) {
@@ -347,11 +346,6 @@ class Rtsp {
347346
this.videoDecoder?.requestYuvBytes = requestYuvBytes
348347
}
349348

350-
fun setRequestNv21Bytes(requestNv21Bytes: Boolean) {
351-
this.requestNv21Bytes = requestNv21Bytes
352-
this.videoDecoder?.requestNv21Bytes = requestNv21Bytes
353-
}
354-
355349
fun setRequestBitmap(requestBitmap: Boolean) {
356350
this.requestBitmap = requestBitmap
357351
this.videoDecoder?.requestBitmap = requestBitmap
@@ -380,7 +374,7 @@ class Rtsp {
380374
surfaceView?.holder?.addCallback(surfaceCallback)
381375
videoDecoder?.stopAsync()
382376
videoDecoder = VideoDecoder(
383-
surface = null, surfaceView, requestMediaImage, requestYuvBytes, requestNv21Bytes, requestBitmap,
377+
surface = null, surfaceView, requestMediaImage, requestYuvBytes, requestBitmap,
384378
videoMimeType, sdpInfo.videoTrack!!.frameWidth, sdpInfo.videoTrack!!.frameHeight, rotation = 0,
385379
videoQueue, clientListener = clientListener
386380
)

0 commit comments

Comments
 (0)