Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add convertation from YUYV to h264, now QGroundControl can see our st… #369

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -69,7 +69,7 @@ ts-rs = "7.1"
cached = { version = "0.48", features = ["serde", "serde_json", "async_tokio_rt_multi_thread"] }

## Mavlink
mavlink = { version = "0.10.6", features = ["default", "emit-extensions"] }
mavlink = { version = "0.10.7", features = ["default", "emit-extensions"] }

## WebRTC
async-tungstenite = { version = "0.25", features = ["tokio-runtime", "tokio-native-tls"] }
Expand Down
3 changes: 3 additions & 0 deletions Cross.toml
Expand Up @@ -6,3 +6,6 @@ image = "joaoantoniocardoso/cross-rs:armv7-unknown-linux-gnueabihf-bullseye-slim

[target.aarch64-unknown-linux-gnu]
image = "joaoantoniocardoso/cross-rs:aarch64-unknown-linux-gnu-bullseye-slim-with-gstreamer"

[target.aarch64-buildroot-linux-gnu]
image = "joaoantoniocardoso/companion-base:update-gstreamer"
10 changes: 5 additions & 5 deletions docker/Dockerfile
@@ -1,4 +1,4 @@
from ubuntu:22.04
FROM ubuntu:22.04

RUN apt update -y && \
apt install -y --no-install-recommends \
Expand All @@ -15,10 +15,10 @@ RUN apt update -y && \

# We need libssl.so.1.1
# Note: if the link breaks, find it here: http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/?C=M;O=D
RUN wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.21_amd64.deb && \
dpkg -i libssl1.1_1.1.1f-1ubuntu2.21_amd64.deb ; \
rm -rf libssl1.1_1.1.1f-1ubuntu2.21_amd64.deb
RUN wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.22_amd64.deb && \
dpkg -i libssl1.1_1.1.1f-1ubuntu2.22_amd64.deb ; \
rm -rf libssl1.1_1.1.1f-1ubuntu2.22_amd64.deb

COPY ./target/x86_64-unknown-linux-gnu/release/mavlink-camera-manager /

ENTRYPOINT ./mavlink-camera-manager --mavlink=tcpout:192.168.2.2:5777 --verbose --reset
ENTRYPOINT ./mavlink-camera-manager --mavlink=tcpout:0.0.0.0:5777 --verbose --reset
7 changes: 6 additions & 1 deletion docker/build_and_run.sh
Expand Up @@ -9,4 +9,9 @@ cross build --release --target=x86_64-unknown-linux-gnu
docker build -t $USER/mavlink-camera-manager:$(git rev-parse HEAD) -f ./docker/Dockerfile .

# Run
docker run -it --net=host $USER/mavlink-camera-manager:$(git rev-parse HEAD)
docker run -it --rm --network host\
--privileged\
-v /dev:/dev\
-v /sys/devices:/sys/devices\
-v ./logs:/logs\
$USER/mavlink-camera-manager:$(git rev-parse HEAD)\
8 changes: 5 additions & 3 deletions src/mavlink/mavlink_camera.rs
Expand Up @@ -138,9 +138,8 @@ impl MavlinkCameraInner {
let component_id = camera.component.component_id;
let system_id = camera.component.system_id;

let mut period = tokio::time::interval(tokio::time::Duration::from_secs(1));
loop {
period.tick().await;
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;

let header = mavlink::MavHeader {
system_id,
Expand Down Expand Up @@ -277,7 +276,10 @@ impl MavlinkCameraInner {
focal_length: 0.0,
sensor_size_h: 0.0,
sensor_size_v: 0.0,
flags: mavlink::common::CameraCapFlags::CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM,
flags: mavlink::common::CameraCapFlags::CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM |
mavlink::common::CameraCapFlags::CAMERA_CAP_FLAGS_CAN_CAPTURE_IMAGE_IN_VIDEO_MODE |
mavlink::common::CameraCapFlags::CAMERA_CAP_FLAGS_HAS_BASIC_ZOOM |
mavlink::common::CameraCapFlags::CAMERA_CAP_FLAGS_HAS_BASIC_FOCUS,
resolution_h: camera.component.resolution_h,
resolution_v: camera.component.resolution_v,
cam_definition_version: 0,
Expand Down
8 changes: 5 additions & 3 deletions src/stream/pipeline/v4l_pipeline.rs
Expand Up @@ -78,9 +78,11 @@ impl V4lPipeline {
concat!(
"v4l2src device={device} do-timestamp=true",
" ! videoconvert",
" ! capsfilter name={filter_name} caps=video/x-raw,format=I420,width={width},height={height},framerate={interval_denominator}/{interval_numerator}",
" ! x264enc",
" ! h264parse",
" ! capsfilter name={filter_name} caps=video/x-h264,stream-format=avc,alignment=au,width={width},height={height},framerate={interval_denominator}/{interval_numerator}",
Comment on lines -81 to +83
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that we can accomplish the same thing with decodebin3 here, and letting it taking decision over the encoders. @joaoantoniocardoso what you think ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we could use encodebin/encodebin2 to be more robust.

I believe transcoding should be an option, and not change today's default behavior, as people might be using raw video streams right now.

" ! tee name={video_tee_name} allow-not-linked=true",
" ! rtpvrawpay pt=96",
" ! rtph264pay aggregate-mode=zero-latency config-interval=10 pt=96",
" ! tee name={rtp_tee_name} allow-not-linked=true"
),
device = device,
Expand Down Expand Up @@ -120,7 +122,7 @@ impl V4lPipeline {
}
};

debug!("pipeline_description: {description:#?}");
debug!("pipeline_description: {description:?}");

let pipeline = gst::parse::launch(&description)?;

Expand Down
14 changes: 13 additions & 1 deletion src/stream/sink/image_sink.rs
Expand Up @@ -352,7 +352,19 @@ impl ImageSink {
decoder.has_property("discard-corrupted-frames", None).then(|| decoder.set_property("discard-corrupted-frames", true));
_transcoding_elements.push(decoder);
}
VideoEncodeType::Yuyv => {}
VideoEncodeType::Yuyv => {
// For h264, we need to filter-out unwanted non-key frames here, before decoding it.
let filter = gst::ElementFactory::make("identity")
.property("drop-buffer-flags", gst::BufferFlags::DELTA_UNIT)
.property("sync", false)
.build()?;
let decoder = gst::ElementFactory::make("avdec_h264")
.property_from_str("lowres", "2") // (0) is 'full'; (1) is '1/2-size'; (2) is '1/4-size'
.build()?;
decoder.has_property("discard-corrupted-frames", None).then(|| decoder.set_property("discard-corrupted-frames", true));
_transcoding_elements.push(filter);
_transcoding_elements.push(decoder);
}
_ => return Err(anyhow!("Unsupported video encoding for ImageSink: {encoding:?}. The supported are: H264, MJPG and YUYV")),
};

Expand Down