User Guide

Use the PDrAW program

The PDrAW program can be used to display a live stream from an Anafi, connected directly with wifi or through a SkyController 3.

Note

For macOS users, replace the following parts of example command lines:

  • native-wrapper.sh with native-darwin-wrapper.sh
  • pdraw-linux with pdraw-macos
# Run from the workspace root directory
$ ./out/pdraw-linux/staging/native-wrapper.sh pdraw -u rtsp://192.168.42.1/live
# Or rtsp://192.168.53.1/live if connected through a SkyController3

It can also be used to replay a file from the drone memory/SD-card

# Run from the workspace root directory
$ ./out/pdraw-linux/staging/native-wrapper.sh pdraw -u rtsp://192.168.42.1/replay/100000010001.MP4
# Or rtsp://192.168.53.1/replay/XXXX if connected through a SkyController3
# The replay URL can be queried from the Anafi webserver http://anafi.local

Or play a local file

# Run from the workspace root directory
$ ./out/pdraw-linux/staging/native-wrapper.sh pdraw -u path/to/file.mp4
# No need to be connected to a drone!

Further options can be found with the -h flag, e.g.:

  • --hud adds an overlayed display on the video, computed from the metadata
  • --zebras enables overexposure zebra computation

Build your own app with libpdraw-backend

To build an application using libpdraw-backend, you can either use alchemy to build your app, or use your own build system.

Note

The same applies when using libpdraw directly, but your app will be responsible for providing and running the pomp_loop.

Using Alchemy to create a new executable

Alchemy searches for modules in the packages directory of your SDK workspace. For this example, we will create an application in the <SDK>/packages/test-app directory.

First, create an atom.mk file in this directory. This file tells Alchemy what to build, and which dependencies are required:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# LOCAL_MODULE is the name of your app.
LOCAL_MODULE := test-app
# LOCAL_LIBRARIES is the list of libraries your app depends on.
LOCAL_LIBRARIES := libpdraw-backend
# LOCAL_SRC_FILES is the list of source files in your app.
LOCAL_SRC_FILES := main.c

include $(BUILD_EXECUTABLE)

Then create a main.c file. The provided example creates a pdraw-backend instance, opens the given url (or local path), then closes the instance. It implements the very basic operation of libpdraw-backend, and is sufficient to check if the binary is properly linked.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <pdraw/pdraw_backend.h>

#include <pthread.h>
#include <stdio.h>
#include <string.h>

struct ctx {
	pthread_mutex_t mutex;
	pthread_cond_t cond;
	int status;
};

static void
pdraw_open_resp(struct pdraw_backend *pdraw, int status, void *userdata)
{
	struct ctx *ctx = userdata;
	printf("pdraw_open_resp: %d (%s)\n", status, strerror(-status));
	ctx->status = status;
	pthread_mutex_lock(&ctx->mutex);
	pthread_cond_signal(&ctx->cond);
	pthread_mutex_unlock(&ctx->mutex);
}

static void
pdraw_close_resp(struct pdraw_backend *pdraw, int status, void *userdata)
{
	struct ctx *ctx = userdata;
	printf("pdraw_close_resp: %d (%s)\n", status, strerror(-status));
	ctx->status = status;
	pthread_mutex_lock(&ctx->mutex);
	pthread_cond_signal(&ctx->cond);
	pthread_mutex_unlock(&ctx->mutex);
}

static const struct pdraw_backend_cbs backend_cbs = {
	.open_resp = pdraw_open_resp,
	.close_resp = pdraw_close_resp,
};

int main(int argc, char *argv[])
{
	struct pdraw_backend *pdraw;
	struct ctx ctx;
	int ret;

	if (argc < 2) {
		fprintf(stderr, "Missing argument\n");
		return 1;
	}

	pthread_mutex_init(&ctx.mutex, NULL);
	pthread_cond_init(&ctx.cond, NULL);

	ret = pdraw_be_new(&backend_cbs, &ctx, &pdraw);
	if (ret != 0) {
		fprintf(stderr, "pdraw_be_new: %d (%s)\n", ret, strerror(-ret));
		goto clean_cond;
	}

	ret = pdraw_be_open_url(pdraw, argv[1]);
	if (ret != 0) {
		fprintf(stderr,
			"pdraw_be_open_url: %d (%s)\n",
			ret,
			strerror(-ret));
		goto exit;
	}

	/* Wait for open resp */
	pthread_cond_wait(&ctx.cond, &ctx.mutex);
	if (ctx.status != 0)
		goto exit;

	ret = pdraw_be_close(pdraw);
	if (ret != 0) {
		fprintf(stderr,
			"pdraw_be_close: %d (%s)\n",
			ret,
			strerror(-ret));
		goto exit;
	}

	/* Wait for close resp */
	pthread_cond_wait(&ctx.cond, &ctx.mutex);

exit:
	pdraw_be_destroy(pdraw);
clean_cond:
	pthread_mutex_destroy(&ctx.mutex);
	pthread_cond_destroy(&ctx.cond);
	return ret;
}

The application can then be built with the following command:

# Run from the workspace root directory
$ ./build.sh -p pdraw-linux -A test-app -j/1

And run with the following command:

# Run from the workspace root directory
$ ./out/pdraw-linux/staging/native-wrapper.sh test-app rtsp://192.168.42.1/live

Using a custom build system with the SDK libraries

If you don’t want to use Alchemy to build your app, you can directly use the output files from the Alchemy build (libraries and headers) from any other build system.

First, we need to build the SDK from Alchemy to be used externally:

# Run from the workspace root directory
$ ./build.sh -p pdraw-linux -A sdk -j/1

For this example, we will use the same main file from the Alchemy sample, and assume that the SDK was properly built from a folder called <SDK>. The following makefile can be used to build the same binary as before, but outside of the Alchemy build system:

BIN := test-app
SRC := main.c
OBJ := $(SRC:.c=.o)

# Change this to point to your SDK dir
SDK_DIR := ../../../..
SDK_INC_DIR := $(SDK_DIR)/out/pdraw-linux/sdk/usr/include
SDK_LIB_DIR := $(SDK_DIR)/out/pdraw-linux/sdk/usr/lib

all: $(BIN)

$(BIN): $(OBJ)
	@gcc -o $@ -L$(SDK_LIB_DIR) -Wl,-rpath=$(SDK_LIB_DIR) $^ -lpdraw-backend

%.o: %.c
	@gcc -c -o $@ -I$(SDK_INC_DIR) $<

clean:
	@rm -f $(OBJ) $(BIN)

.PHONY: clean

As the libraries from Alchemy are not installed in the system directories, you have to provide the library path to the loader when running the result binary:

# Run from your Makefile/main.c directory
$ make
$ env LD_LIBRARY_PATH=<SDK>/out/pdraw-linux/sdk/usr/lib ./test-app rtsp://192.168.43.1/live