mirror of
https://github.com/gtxaspec/wz_mini_hacks.git
synced 2024-11-22 13:37:19 +00:00
add second stream to rtsp
This commit is contained in:
parent
94b2aad718
commit
ad42670438
27
README.md
27
README.md
@ -183,23 +183,31 @@ ENABLE_NFSv4="true"
|
||||
|
||||
---
|
||||
RTSP streaming:
|
||||
You can choose to enable or disable audio. Set your login credentials here, server listening port, and the stream bitrate.
|
||||
(RTSP_ENC_PARAMETER variable accepts numbers only. 0=FIXQP, 1=CBR, 2=VBR, 4=CAPPED VBR, 8=CAPPED QUALITY. Currently only 2, 4, and 8 are working)
|
||||
The RTSP server outputs the two supported video streams from the camera, 1080p/360p (1296p/480p for the DB3). You can choose to enable a single stream of your choice, or both. Audio is also available. Set your login credentials here, server listening port, and the stream bitrate.
|
||||
(ENC_PARAMETER variable accepts numbers only. 0=FIXQP, 1=CBR, 2=VBR, 4=CAPPED VBR, 8=CAPPED QUALITY. Currently only 2, 4, and 8 are working)
|
||||
|
||||
```
|
||||
RTSP_ENABLED="true"
|
||||
RTSP_ENABLE_AUDIO="true"
|
||||
RTSP_LOGIN="admin"
|
||||
RTSP_PASSWORD=""
|
||||
RTSP_PORT="8554"
|
||||
RTSP_MAX_BITRATE="2048"
|
||||
RTSP_TARGET_BITRATE="1024"
|
||||
RTSP_ENC_PARAMETER="2"
|
||||
|
||||
RTSP_HI_RES_ENABLED="true"
|
||||
RTSP_HI_RES_ENABLE_AUDIO="true"
|
||||
RTSP_HI_RES_PORT="8554"
|
||||
RTSP_HI_RES_MAX_BITRATE="2048"
|
||||
RTSP_HI_RES_TARGET_BITRATE="1024"
|
||||
RTSP_HI_RES_ENC_PARAMETER="2"
|
||||
|
||||
RTSP_LOW_RES_ENABLED="false"
|
||||
RTSP_LOW_RES_ENABLE_AUDIO="false"
|
||||
RTSP_LOW_RES_PORT="8555"
|
||||
RTSP_LOW_RES_MAX_BITRATE=""
|
||||
RTSP_LOW_RES_TARGET_BITRATE=""
|
||||
RTSP_LOW_RES_ENC_PARAMETER=""
|
||||
|
||||
```
|
||||
the stream will be located at ```rtsp://login:password@IP_ADDRESS:8554/unicast```
|
||||
|
||||
Notes: If you don't set the password, then the password will be the unique MAC address of the camera, in all uppercase, including the colons... for example:. AA:BB:CC:00:11:22. It's typically printed on the camera. VLC seems to work fine for playback, ffmpeg and others have severe artifacts in the stream during playback.
|
||||
Notes: If you don't set the password, then the password will be the unique MAC address of the camera, in all uppercase, including the colons... for example:. AA:BB:CC:00:11:22. It's typically printed on the camera. Higher video bitrates may overload your Wi-Fi connection, so a wired connection is recommended.
|
||||
|
||||
Huge credit to @mnakada for his libcallback library: [https://github.com/mnakada/atomcam_tools](https://github.com/mnakada/atomcam_tools)
|
||||
|
||||
@ -207,6 +215,7 @@ Huge credit to @mnakada for his libcallback library: [https://github.com/mnakada
|
||||
|
||||
## Latest Updates
|
||||
|
||||
* 05-15-22: patched libcallback to support both video streams from the camera. Added support for them in run_mmc.sh.
|
||||
* 05-14-22: Added ability to specify RTSP bitrate parameters. Note that changing bitrate in the mobile app will briefly reset the bitrate for the RTSP stream.
|
||||
* 05-14-22: Update v4l2rtspserver, tinyalsa, alsa-lib. Patch busybox for older official FW's failing to run scripts, fix choppy/static audio in libcallback
|
||||
* 05-09-22: fix bug in run_mmc.sh that did not store the wlan mac when using a wired usb or ethernet connection for the rtsp server
|
||||
|
@ -11,11 +11,21 @@ set -x
|
||||
|
||||
echo "v3_post.sh exec"
|
||||
|
||||
if [[ $(cat /opt/wz_mini/run_mmc.sh | grep "RTSP_ENABLED\=") == "RTSP_ENABLED\=\"true\"" ]] && ! [[ -e /tmp/dbgflag ]]; then
|
||||
|
||||
if [[ $(cat /opt/wz_mini/run_mmc.sh | grep "RTSP_HI_RES_ENABLED\=") == "RTSP_HI_RES_ENABLED\=\"true\"" ]] || [[ $(cat /opt/wz_mini/run_mmc.sh | grep "RTSP_LOW_RES_ENABLED\=") == "RTSP_LOW_RES_ENABLED\=\"true\"" ]] && ! [[ -e /tmp/dbgflag ]]; then
|
||||
if [[ $(cat /opt/wz_mini/run_mmc.sh | grep "RTSP_LOW_RES_ENABLED\=") == "RTSP_LOW_RES_ENABLED\=\"true\"" ]] && [[ $(cat /opt/wz_mini/run_mmc.sh | grep "RTSP_HI_RES_ENABLED\=") == "RTSP_HI_RES_ENABLED\=\"true\"" ]]; then
|
||||
echo "load video loopback driver at video1 video2"
|
||||
insmod /opt/wz_mini/lib/modules/v4l2loopback.ko video_nr=1,2
|
||||
elif [[ $(cat /opt/wz_mini/run_mmc.sh | grep "RTSP_LOW_RES_ENABLED\=") == "RTSP_LOW_RES_ENABLED\=\"true\"" ]]; then
|
||||
echo "load video loopback driver at video2"
|
||||
insmod /opt/wz_mini/lib/modules/v4l2loopback.ko video_nr=2
|
||||
elif [[ $(cat /opt/wz_mini/run_mmc.sh | grep "RTSP_HI_RES_ENABLED\=") == "RTSP_HI_RES_ENABLED\=\"true\"" ]]; then
|
||||
echo "load video loopback driver at video1"
|
||||
insmod /opt/wz_mini/lib/modules/v4l2loopback.ko video_nr=1
|
||||
fi
|
||||
|
||||
cp /system/bin/iCamera /opt/wz_mini/tmp/.storage/
|
||||
mount -o ro,bind /opt/wz_mini/usr/bin/iCamera /system/bin/iCamera
|
||||
echo "load video loopback driver at video1"
|
||||
insmod /opt/wz_mini/lib/modules/v4l2loopback.ko video_nr=1
|
||||
fi
|
||||
|
||||
##LIBRARY DEBUG
|
||||
|
Binary file not shown.
@ -30,14 +30,22 @@ REMOTE_SPOTLIGHT="false"
|
||||
REMOTE_SPOTLIGHT_HOST="0.0.0.0"
|
||||
|
||||
#####VIDEO STREAM#####
|
||||
RTSP_ENABLED="false"
|
||||
RTSP_ENABLE_AUDIO="false"
|
||||
RTSP_LOGIN="admin"
|
||||
RTSP_PASSWORD=""
|
||||
RTSP_PORT="8554"
|
||||
RTSP_MAX_BITRATE=""
|
||||
RTSP_TARGET_BITRATE=""
|
||||
RTSP_ENC_PARAMETER=""
|
||||
|
||||
RTSP_HI_RES_ENABLED="false"
|
||||
RTSP_HI_RES_ENABLE_AUDIO="false"
|
||||
RTSP_HI_RES_PORT="8554"
|
||||
RTSP_HI_RES_MAX_BITRATE=""
|
||||
RTSP_HI_RES_TARGET_BITRATE=""
|
||||
RTSP_HI_RES_ENC_PARAMETER=""
|
||||
|
||||
RTSP_LOW_RES_ENABLED="false"
|
||||
RTSP_LOW_RES_ENABLE_AUDIO="false"
|
||||
RTSP_LOW_RES_PORT="8555"
|
||||
RTSP_LOW_RES_MAX_BITRATE=""
|
||||
RTSP_LOW_RES_TARGET_BITRATE=""
|
||||
RTSP_LOW_RES_ENC_PARAMETER=""
|
||||
|
||||
#####GENERAL#####
|
||||
ENABLE_SWAP="true"
|
||||
@ -345,7 +353,7 @@ else
|
||||
echo "remote accessory disabled"
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_ENABLED" == "true" ]]; then
|
||||
if [[ "$RTSP_HI_RES_ENABLED" == "true" ]]; then
|
||||
|
||||
if [[ "$ENABLE_SWAP" == "true" ]]; then
|
||||
echo "swap already enabled"
|
||||
@ -361,23 +369,22 @@ if [[ "$RTSP_ENABLED" == "true" ]]; then
|
||||
RTSP_PASSWORD=$(cat /opt/wz_mini/tmp/wlan0_mac)
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_ENABLE_AUDIO" == "true" ]]; then
|
||||
LD_LIBRARY_PATH=/media/mmc/wz_mini/lib /media/mmc/wz_mini/bin/v4l2rtspserver -C 1 -a S16_LE /dev/video1,hw:Loopback,0 -U $RTSP_LOGIN:$RTSP_PASSWORD -P $RTSP_PORT &
|
||||
if [[ "$RTSP_HI_RES_ENABLE_AUDIO" == "true" ]]; then
|
||||
LD_LIBRARY_PATH=/media/mmc/wz_mini/lib /media/mmc/wz_mini/bin/v4l2rtspserver -C 1 -a S16_LE /dev/video1,hw:Loopback,0 -U $RTSP_LOGIN:$RTSP_PASSWORD -P $RTSP_HI_RES_PORT &
|
||||
else
|
||||
echo "rtsp audio disabled"
|
||||
LD_LIBRARY_PATH=/media/mmc/wz_mini/lib /media/mmc/wz_mini/bin/v4l2rtspserver -s /dev/video1 -U $RTSP_LOGIN:$RTSP_PASSWORD -P $RTSP_PORT &
|
||||
LD_LIBRARY_PATH=/media/mmc/wz_mini/lib /media/mmc/wz_mini/bin/v4l2rtspserver -s /dev/video1 -U $RTSP_LOGIN:$RTSP_PASSWORD -P $RTSP_HI_RES_PORT &
|
||||
fi
|
||||
|
||||
|
||||
if [[ "$RTSP_ENC_PARAMETER" != "" ]]; then
|
||||
if [[ "$RTSP_HI_RES_ENC_PARAMETER" != "" ]]; then
|
||||
watch -n5 -t "/system/bin/impdbg --enc_rc_s 0:44:4:$RTSP_ENC_PARAMETER" > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_MAX_BITRATE" != "" ]]; then
|
||||
if [[ "$RTSP_HI_RES_MAX_BITRATE" != "" ]]; then
|
||||
watch -n5 -t "/system/bin/impdbg --enc_rc_s 0:48:4:$RTSP_MAX_BITRATE" > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_TARGET_BITRATE" != "" ]]; then
|
||||
if [[ "$RTSP_HI_RES_TARGET_BITRATE" != "" ]]; then
|
||||
watch -n5 -t "/system/bin/impdbg --enc_rc_s 0:52:4:$RTSP_TARGET_BITRATE" > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
@ -386,6 +393,46 @@ if [[ "$RTSP_ENABLED" == "true" ]]; then
|
||||
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_LOW_RES_ENABLED" == "true" ]]; then
|
||||
|
||||
if [[ "$ENABLE_SWAP" == "true" ]]; then
|
||||
echo "swap already enabled"
|
||||
else
|
||||
swap_enable
|
||||
fi
|
||||
|
||||
/opt/wz_mini/bin/cmd video on1
|
||||
/opt/wz_mini/bin/cmd audio on
|
||||
|
||||
|
||||
if [[ "$RTSP_PASSWORD" = "" ]]; then
|
||||
RTSP_PASSWORD=$(cat /opt/wz_mini/tmp/wlan0_mac)
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_LOW_RES_ENABLE_AUDIO" == "true" ]]; then
|
||||
LD_LIBRARY_PATH=/media/mmc/wz_mini/lib /media/mmc/wz_mini/bin/v4l2rtspserver -C 1 -a S16_LE /dev/video2,hw:Loopback,0 -U $RTSP_LOGIN:$RTSP_PASSWORD -P $RTSP_LOW_RES_PORT &
|
||||
else
|
||||
echo "rtsp audio disabled"
|
||||
LD_LIBRARY_PATH=/media/mmc/wz_mini/lib /media/mmc/wz_mini/bin/v4l2rtspserver -s /dev/video2 -U $RTSP_LOGIN:$RTSP_PASSWORD -P $RTSP_LOW_RES_PORT &
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_LOW_RES_ENC_PARAMETER" != "" ]]; then
|
||||
watch -n5 -t "/system/bin/impdbg --enc_rc_s 1:44:4:$RTSP_ENC_PARAMETER" > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_LOW_RES_MAX_BITRATE" != "" ]]; then
|
||||
watch -n5 -t "/system/bin/impdbg --enc_rc_s 1:48:4:$RTSP_MAX_BITRATE" > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
if [[ "$RTSP_LOW_RES_TARGET_BITRATE" != "" ]]; then
|
||||
watch -n5 -t "/system/bin/impdbg --enc_rc_s 1:52:4:$RTSP_TARGET_BITRATE" > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
else
|
||||
echo "rtsp disabled"
|
||||
|
||||
fi
|
||||
|
||||
touch /opt/wz_mini/tmp/.run_mmc_firstrun
|
||||
sync;echo 3 > /proc/sys/vm/drop_caches
|
||||
sleep 3
|
||||
|
Binary file not shown.
@ -19,7 +19,9 @@ typedef int (* framecb)(struct frames_st *);
|
||||
|
||||
static int (*real_local_sdk_video_set_encode_frame_callback)(int ch, void *callback);
|
||||
static void *video_encode_cb = NULL;
|
||||
static void *video_encode_cb1 = NULL;
|
||||
static int VideoCaptureEnable = 0;
|
||||
static int VideoCaptureEnable1 = 0;
|
||||
|
||||
char *VideoCapture(int fd, char *tokenPtr) {
|
||||
|
||||
@ -27,12 +29,22 @@ char *VideoCapture(int fd, char *tokenPtr) {
|
||||
if(!p) return VideoCaptureEnable ? "on" : "off";
|
||||
if(!strcmp(p, "on")) {
|
||||
VideoCaptureEnable = 1;
|
||||
fprintf(stderr, "[command] video capute on\n", p);
|
||||
fprintf(stderr, "[command] video capture ch0 on\n", p);
|
||||
return "ok";
|
||||
}
|
||||
if(!strcmp(p, "on1")) {
|
||||
VideoCaptureEnable1 = 1;
|
||||
fprintf(stderr, "[command] video capture ch1 on\n", p);
|
||||
return "ok";
|
||||
}
|
||||
if(!strcmp(p, "off")) {
|
||||
VideoCaptureEnable = 0;
|
||||
fprintf(stderr, "[command] video capute off\n", p);
|
||||
fprintf(stderr, "[command] video capture ch0 off\n", p);
|
||||
return "ok";
|
||||
}
|
||||
if(!strcmp(p, "off1")) {
|
||||
VideoCaptureEnable1 = 0;
|
||||
fprintf(stderr, "[command] video capture ch1 off\n", p);
|
||||
return "ok";
|
||||
}
|
||||
return "error";
|
||||
@ -43,6 +55,7 @@ static uint32_t video_encode_capture(struct frames_st *frames) {
|
||||
static int firstEntry = 0;
|
||||
static int v4l2Fd = -1;
|
||||
|
||||
//primary stream 0
|
||||
if(!firstEntry) {
|
||||
firstEntry++;
|
||||
int err;
|
||||
@ -86,19 +99,78 @@ static uint32_t video_encode_capture(struct frames_st *frames) {
|
||||
return ((framecb)video_encode_cb)(frames);
|
||||
}
|
||||
|
||||
//secondary stream 1
|
||||
static uint32_t video_encode_capture1(struct frames_st *frames) {
|
||||
|
||||
static int firstEntry = 0;
|
||||
static int v4l2Fd = -1;
|
||||
|
||||
if(!firstEntry) {
|
||||
firstEntry++;
|
||||
int err;
|
||||
const char *v4l2_device_path = "/dev/video2";
|
||||
const char *productf="/configs/.product_db3";
|
||||
fprintf(stderr,"Opening V4L2 device: %s \n", v4l2_device_path);
|
||||
v4l2Fd = open(v4l2_device_path, O_WRONLY, 0777);
|
||||
if(v4l2Fd < 0) fprintf(stderr,"Failed to open V4L2 device: %s\n", v4l2_device_path);
|
||||
struct v4l2_format vid_format;
|
||||
memset(&vid_format, 0, sizeof(vid_format));
|
||||
vid_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
|
||||
|
||||
if( access( productf, F_OK ) == 0 ) {
|
||||
/* doorbell resolution */
|
||||
printf("[command] video product 640x480");
|
||||
vid_format.fmt.pix.width = 640;
|
||||
vid_format.fmt.pix.height = 480;
|
||||
} else {
|
||||
/* v3 and panv2 res */
|
||||
printf("[command] video product 640x320");
|
||||
vid_format.fmt.pix.width = 640;
|
||||
vid_format.fmt.pix.height = 320;
|
||||
}
|
||||
|
||||
vid_format.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
|
||||
vid_format.fmt.pix.sizeimage = 0;
|
||||
vid_format.fmt.pix.field = V4L2_FIELD_NONE;
|
||||
vid_format.fmt.pix.bytesperline = 0;
|
||||
vid_format.fmt.pix.colorspace = V4L2_PIX_FMT_YUV420;
|
||||
err = ioctl(v4l2Fd, VIDIOC_S_FMT, &vid_format);
|
||||
if(err < 0) fprintf(stderr,"Unable to set V4L2 device video format: %d\n", err);
|
||||
err = ioctl(v4l2Fd, VIDIOC_STREAMON, &vid_format);
|
||||
if(err < 0) fprintf(stderr,"Unable to perform VIDIOC_STREAMON: %d\n", err);
|
||||
}
|
||||
|
||||
if( (v4l2Fd >= 0) && VideoCaptureEnable) {
|
||||
uint32_t *buf = frames->buf;
|
||||
int size = write(v4l2Fd, frames->buf, frames->length);
|
||||
if(size != frames->length) fprintf(stderr,"Stream write error: %s\n", size);
|
||||
}
|
||||
return ((framecb)video_encode_cb1)(frames);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int local_sdk_video_set_encode_frame_callback(int ch, void *callback) {
|
||||
|
||||
fprintf(stderr, "local_sdk_video_set_encode_frame_callback streamChId=%d, callback=0x%x\n", ch, callback);
|
||||
static int ch_count = 0;
|
||||
|
||||
/* two callbacks typically detected, unknown what the difference is between them, but if they are both hooked, the app breaks. grab just one of them. */
|
||||
|
||||
/* two callbacks for video stream 0 are typically detected, unknown what the difference is between them, but if they are both hooked, the app breaks. grab just one of them. */
|
||||
//stream 0
|
||||
if( (ch == 0) && ch_count == 2) {
|
||||
video_encode_cb = callback;
|
||||
fprintf(stderr,"enc func injection save video_encode_cb=0x%x\n", video_encode_cb);
|
||||
callback = video_encode_capture;
|
||||
}
|
||||
fprintf(stderr,"ch count is %x\n", ch_count);
|
||||
|
||||
//stream 1
|
||||
if( (ch == 1) && ch_count == 1) {
|
||||
video_encode_cb1 = callback;
|
||||
fprintf(stderr,"enc func injection save video_encode_cb=0x%x\n", video_encode_cb1);
|
||||
callback = video_encode_capture1;
|
||||
}
|
||||
|
||||
ch_count=ch_count+1;
|
||||
|
||||
return real_local_sdk_video_set_encode_frame_callback(ch, callback);
|
||||
|
Loading…
Reference in New Issue
Block a user