Capture the video streaming and its metadata#

Once you are connected to a drone with Olympe, to start the video streaming just call the olympe.Drone.streaming.start() function and the drone will start sending its video stream to Olympe. Call olympe.Drone.streaming.stop() the video streaming.

Realtime capture#

Before you start the video streaming, you can register some callback functions that will be called whenever Olympe receive/decode a new video frame. See set_streaming_callbacks().

Record the live/replayed video stream for a post-processing#

Before you start the video streaming, you can specify some output files that will be used by Olympe to record the video stream and its metadata. set_streaming_output_files().

Video streaming example#

The following example shows how to get the video stream from the drone using Olympe. Internally, Olympe leverages Parrot libpdraw to:

  • initialize the video streaming from the drone

  • decode the H.264 video stream

  • register user provided callback functions that are called for each (encoded or decoded) frame with its associated metadata

  • record the live video stream from the drone to the disk

When using Olympe to access the video stream you can’t use the PDrAW standalone executable to view the video stream (the drone only supports one video client at a time).

For this example, we first create a fixture class that will hold our olympe.Drone object and some H.264 statistics.

30
31class StreamingExample:
32    def __init__(self):
33        # Create the olympe.Drone object from its IP address
34        self.drone = olympe.Drone(DRONE_IP)
35        self.tempd = tempfile.mkdtemp(prefix="olympe_streaming_test_")
36        print(f"Olympe streaming example output dir: {self.tempd}")
37        self.h264_frame_stats = []
38        self.h264_stats_file = open(os.path.join(self.tempd, "h264_stats.csv"), "w+")
39        self.h264_stats_writer = csv.DictWriter(
40            self.h264_stats_file, ["fps", "bitrate"]
41        )
42        self.h264_stats_writer.writeheader()
43        self.frame_queue = queue.Queue()
44        self.processing_thread = threading.Thread(target=self.yuv_frame_processing)

Our objective is to start the video stream, fly the drone around, perform some live video processing, stop the video stream and finally perform some video postprocessing.

200def test_streaming():
201    streaming_example = StreamingExample()
202    # Start the video stream
203    streaming_example.start()
204    # Perform some live video processing while the drone is flying
205    streaming_example.fly()
206    # Stop the video stream
207    streaming_example.stop()
208    # Recorded video stream postprocessing
209    # streaming_example.replay_with_vlc()

Before we start the video streaming, we must connect to the drone and optionally register our callback functions and output files for the recorded video stream.

46
47    def start(self):
48        # Connect to drone
49        assert self.drone.connect(retry=3)
50
51        if DRONE_RTSP_PORT is not None:
52            self.drone.streaming.server_addr = f"{DRONE_IP}:{DRONE_RTSP_PORT}"
53
54        # You can record the video stream from the drone if you plan to do some
55        # post processing.
56        self.drone.streaming.set_output_files(
57            video=os.path.join(self.tempd, "streaming.mp4"),
58            metadata=os.path.join(self.tempd, "streaming_metadata.json"),
59        )
60
61        # Setup your callback functions to do some live video processing
62        self.drone.streaming.set_callbacks(
63            raw_cb=self.yuv_frame_cb,
64            h264_cb=self.h264_frame_cb,
65            start_cb=self.start_cb,
66            end_cb=self.end_cb,
67            flush_raw_cb=self.flush_cb,
68        )
69        # Start video streaming
70        self.drone.streaming.start()
71        self.renderer = PdrawRenderer(pdraw=self.drone.streaming)
72        self.running = True

The StreamingExample.yuv_frame_cb() and StreamingExample.h264_frame_cb() receives an olympe.VideoFrame() object in parameter that you can use to access a video frame data (see: olympe.VideoFrame.as_ndarray(), olympe.VideoFrame.as_ctypes_pointer()) and its metadata (see: olympe.VideoFrame.info() and olympe.VideoFrame.vmeta()).

The full code of this example can be found in src/olympe/doc/examples/streaming.py.