Skip to content

Commit b99c830

Browse files
committed
Intel® ST 2110 Media Streaming Library v0.7.0 release
Signed-off-by: Frank Du <[email protected]>
1 parent 40fb74e commit b99c830

File tree

167 files changed

+37387
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

167 files changed

+37387
-0
lines changed

.clang-format

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
---
3+
BasedOnStyle: Google
4+
DerivePointerAlignment: false
5+
ColumnLimit: 90

.gitignore

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Prerequisites
2+
*.d
3+
4+
# Object files
5+
*.o
6+
*.ko
7+
*.obj
8+
*.elf
9+
10+
# Linker output
11+
*.ilk
12+
*.map
13+
*.exp
14+
15+
# Precompiled Headers
16+
*.gch
17+
*.pch
18+
19+
# Libraries
20+
*.lib
21+
*.a
22+
*.la
23+
*.lo
24+
25+
# Shared objects (inc. Windows DLLs)
26+
*.dll
27+
*.so
28+
*.so.*
29+
*.dylib
30+
31+
# Executables
32+
*.exe
33+
*.out
34+
*.app
35+
*.i*86
36+
*.x86_64
37+
*.hex
38+
39+
# Debug files
40+
*.dSYM/
41+
*.su
42+
*.idb
43+
*.pdb
44+
45+
# Kernel Module Compile Results
46+
*.mod*
47+
*.cmd
48+
.tmp_versions/
49+
modules.order
50+
Module.symvers
51+
Mkfile.old
52+
dkms.conf
53+
54+
# Ours
55+
.*
56+
*.log
57+
*.patch
58+
*.diff
59+
html/
60+
test.*
61+
build/
62+
core*
63+
assets/

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# dpdk.st.kahawai
2+
3+
## 1. Overview:
4+
The Intel Media Streaming Library is a solution based on DPDK prepared for transmitting and receiving high quality video with low latency. It is compliant to the SMPTE ST 2110 Professional Media Over Managed IP Networks suite of standards.
5+
6+
#### 1.1 Features:
7+
* ST2110-20, ST2110-30, ST2110-40, ST2110-22
8+
* 1080p, 720p, 4k
9+
* FPS59.94, FPS50, FPS29
10+
* YUV 4:2:2 10bit
11+
12+
## 2. Build:
13+
Please refer to [build guide](doc/build.md) for how to build DPDK, ST Kahawai library and the sample app.
14+
15+
## 3. Run:
16+
Please refer to [run guide](doc/run.md) for how to setup and run the sample app.
17+
18+
## 4. Coding style:
19+
Run below command before opening a PR.
20+
```bash
21+
./format-coding.sh
22+
```

app/meson.build

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Copyright (C) 2021 Intel Corporation.
2+
#
3+
# This software and the related documents are Intel copyrighted materials,
4+
# and your use of them is governed by the express license under which they
5+
# were provided to you ("License").
6+
# Unless the License provides otherwise, you may not use, modify, copy,
7+
# publish, distribute, disclose or transmit this software or the related
8+
# documents without Intel's prior written permission.
9+
#
10+
# This software and the related documents are provided as is, with no
11+
# express or implied warranties, other than those that are expressly stated
12+
# in the License.
13+
14+
project('Intel(R) ST DPDK sample app', 'c', default_options: ['c_std=gnu11', 'buildtype=release'], version: '0.1',)
15+
exec_env = host_machine.system()
16+
set_variable('is_windows', exec_env == 'windows')
17+
#allow experimental api
18+
add_global_arguments('-DALLOW_EXPERIMENTAL_API', language : 'c')
19+
20+
libst_dpdk = dependency('libst_dpdk', required : true)
21+
libjson_c = dependency('json-c', required : true)
22+
if not is_windows
23+
libpcap = dependency('pcap', required:true)
24+
endif
25+
libsdl2 = dependency('sdl2', required:true)
26+
27+
#add source file
28+
subdir('src')
29+
subdir('tools')
30+
subdir('sample')
31+
32+
app_c_args = []
33+
34+
#enable warning as error
35+
app_c_args += ['-Werror']
36+
app_c_args += ['-Wall']
37+
if is_windows
38+
libpcap =[]
39+
mingw_root_dir = 'c:\mingw64'
40+
dpdk_root_dir = 'c:\dpdk'
41+
app_c_args += ['-DWINDOWSENV']
42+
app_c_args += ['-Wformat=0']
43+
app_c_args += ['-D__USE_MINGW_ANSI_STDIO']
44+
mingw_include_dir = mingw_root_dir + '''\include'''
45+
windows_include_dir = '..\..\lib\windows'
46+
dpdk_include_dir = dpdk_root_dir + '''\lib\eal\windows\include'''
47+
app_c_args += ['-I' + dpdk_include_dir]
48+
app_c_args += ['-I' + mingw_include_dir]
49+
app_c_args += ['-I' + windows_include_dir]
50+
51+
libdpdkcflags = run_command('pkg-config', '--cflags', 'libdpdk')
52+
libjsonccflags = run_command('pkg-config', '--cflags', 'json-c')
53+
libsdl2cflags = run_command('pkg-config', '--cflags', 'sdl2')
54+
libdpdklinkflags = run_command('pkg-config', '--static', '--libs', 'libdpdk')
55+
56+
app_c_args += [libdpdkcflags.stdout().strip().split()]
57+
app_c_args += [libjsonccflags.stdout().strip().split()]
58+
app_c_args += [libsdl2cflags.stdout().strip().split()]
59+
endif
60+
61+
#simd build option, enable sse4.2 default, todo: do we need AVX2/AVX512 for app ?
62+
app_c_args += ['-msse4.2']
63+
64+
app_ld_args = []
65+
66+
app_ld_args += ['-pthread']
67+
68+
if is_windows
69+
app_ld_args += ['-lmingw32','-lws2_32','-lDbghelp','-lSetupapi','-ldinput8', '-ldxguid', '-ldxerr8', '-lwinmm', '-limm32','-lversion','-lwpcap','-lPacket','-lSDL2','-lSDL2Main','-lmman','-ljson-c']
70+
app_ld_args += ['-Wl,--whole-archive']
71+
app_ld_args += [libdpdklinkflags.stdout().strip().split()]
72+
app_ld_args += ['-Wl,--no-whole-archive']
73+
endif
74+
75+
#build executable
76+
executable('RxTxApp', sources,
77+
c_args : app_c_args,
78+
link_args: app_ld_args,
79+
dependencies: [libst_dpdk, libjson_c, libpcap, libsdl2]
80+
)
81+
82+
executable('ConvApp', conv_sources,
83+
c_args : app_c_args,
84+
link_args: app_ld_args,
85+
)
86+
87+
executable('TxVideoApp', video_tx_sources,
88+
c_args : app_c_args,
89+
link_args: app_ld_args,
90+
dependencies: [libst_dpdk]
91+
)
92+
93+
executable('RxVideoApp', video_rx_sources,
94+
c_args : app_c_args,
95+
link_args: app_ld_args,
96+
dependencies: [libst_dpdk]
97+
)
98+

app/sample/meson.build

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (C) 2021 Intel Corporation.
2+
#
3+
# This software and the related documents are Intel copyrighted materials,
4+
# and your use of them is governed by the express license under which they
5+
# were provided to you ("License").
6+
# Unless the License provides otherwise, you may not use, modify, copy,
7+
# publish, distribute, disclose or transmit this software or the related
8+
# documents without Intel's prior written permission.
9+
#
10+
# This software and the related documents are provided as is, with no
11+
# express or implied warranties, other than those that are expressly stated
12+
# in the License.
13+
14+
video_tx_sources = files('tx_video_sample.c')
15+
video_rx_sources = files('rx_video_sample.c')

app/sample/rx_video_sample.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright (C) 2021 Intel Corporation.
3+
*
4+
* This software and the related documents are Intel copyrighted materials,
5+
* and your use of them is governed by the express license under which they
6+
* were provided to you ("License").
7+
* Unless the License provides otherwise, you may not use, modify, copy,
8+
* publish, distribute, disclose or transmit this software or the related
9+
* documents without Intel's prior written permission.
10+
*
11+
* This software and the related documents are provided as is, with no
12+
* express or implied warranties, other than those that are expressly stated
13+
* in the License.
14+
*
15+
*/
16+
17+
#include <pthread.h>
18+
#include <st_dpdk_api.h>
19+
#include <stdbool.h>
20+
#include <stdio.h>
21+
#include <stdlib.h>
22+
#include <string.h>
23+
#include <unistd.h>
24+
25+
struct app_context {
26+
int idx;
27+
int16_t ready_frame_idx;
28+
int16_t consumer_frame_idx;
29+
int fb_rec;
30+
void* frame_rec[3];
31+
void* handle;
32+
bool stop;
33+
pthread_t app_thread;
34+
pthread_cond_t wake_cond;
35+
pthread_mutex_t wake_mutex;
36+
};
37+
38+
static int rx_frame_ready(void* priv, void* frame) {
39+
struct app_context* s = (struct app_context*)priv;
40+
pthread_mutex_lock(&s->wake_mutex);
41+
// restore the returned frame ptr, since rx_frame_ready callback should be non-blocked.
42+
// the frame should be handled in app thread
43+
s->frame_rec[s->ready_frame_idx] = frame;
44+
s->ready_frame_idx = (s->ready_frame_idx + 1) % 3;
45+
pthread_cond_signal(&s->wake_cond);
46+
pthread_mutex_unlock(&s->wake_mutex);
47+
s->fb_rec++;
48+
return 0;
49+
}
50+
51+
static void* app_rx_video_frame_thread(void* arg) {
52+
struct app_context* s = arg;
53+
int consumer_idx;
54+
void* frame;
55+
56+
while (!s->stop) {
57+
consumer_idx = s->consumer_frame_idx;
58+
consumer_idx++;
59+
if (consumer_idx >= 3) consumer_idx = 0;
60+
if (consumer_idx == s->ready_frame_idx) {
61+
/* no buffer */
62+
pthread_mutex_lock(&s->wake_mutex);
63+
if (!s->stop) pthread_cond_wait(&s->wake_cond, &s->wake_mutex);
64+
pthread_mutex_unlock(&s->wake_mutex);
65+
continue;
66+
}
67+
68+
frame = s->frame_rec[consumer_idx];
69+
// put your handle of frame ptr here, it contains pixels data format in st2110-20
70+
// aligned with the TX transfer pg format
71+
st20_rx_put_framebuff(s->handle, frame);
72+
s->consumer_frame_idx = consumer_idx;
73+
}
74+
75+
return NULL;
76+
}
77+
78+
int main() {
79+
struct st_init_params param;
80+
memset(&param, 0, sizeof(param));
81+
int session_num = 1;
82+
param.num_ports = 1;
83+
strncpy(param.port[ST_PORT_P], "0000:af:00.0", ST_PORT_MAX_LEN);
84+
uint8_t ip[4] = {192, 168, 0, 1};
85+
memcpy(param.sip_addr[ST_PORT_P], ip, ST_IP_ADDR_LEN);
86+
param.flags = ST_FLAG_BIND_NUMA; // default bind to numa
87+
param.log_level = ST_LOG_LEVEL_INFO; // log level. ERROR, INFO, WARNING
88+
param.priv = NULL; // usr ctx pointer
89+
param.ptp_get_time_fn =
90+
NULL; // user regist ptp func, if not regist, the internal pt p will be used
91+
param.tx_sessions_cnt_max = 0;
92+
param.rx_sessions_cnt_max = session_num;
93+
param.lcores = NULL;
94+
st_handle dev_handle = st_init(&param);
95+
if (!dev_handle) {
96+
printf("st_init fail\n");
97+
return -1;
98+
}
99+
st20_rx_handle rx_handle[session_num];
100+
struct app_context* app[session_num];
101+
int ret;
102+
103+
// create and register rx session
104+
for (int i = 0; i < session_num; i++) {
105+
app[i] = (struct app_context*)malloc(sizeof(struct app_context));
106+
if (!app[i]) {
107+
printf(" app struct is not correctly malloc");
108+
return -1;
109+
}
110+
app[i]->idx = i;
111+
struct st20_rx_ops ops_rx;
112+
ops_rx.name = "st20_test";
113+
ops_rx.priv = app[i]; // app handle register to lib
114+
ops_rx.num_port = 1;
115+
uint8_t sip[4] = {239, 168, 0, 1};
116+
memcpy(ops_rx.sip_addr[ST_PORT_P], sip, ST_IP_ADDR_LEN); // tx src ip like 239.0.0.1
117+
strncpy(ops_rx.port[ST_PORT_P], "0000:af:00.0",
118+
ST_PORT_MAX_LEN); // send port interface like 0000:af:00.0
119+
ops_rx.udp_port[ST_PORT_P] =
120+
10000 + i; // user could config the udp port in this interface.
121+
ops_rx.pacing = ST21_PACING_NARROW;
122+
ops_rx.type = ST20_TYPE_FRAME_LEVEL;
123+
ops_rx.width = 1920;
124+
ops_rx.height = 1080;
125+
ops_rx.fps = ST_FPS_P59_94;
126+
ops_rx.fmt = ST20_FMT_YUV_422_10BIT;
127+
ops_rx.framebuff_cnt =
128+
3; // aligned with frame_rec[3] in app_context, framebuf pool size is 3 in lib.
129+
ops_rx.notify_frame_ready =
130+
rx_frame_ready; // app regist non-block func, app could get a frame ready
131+
// notification info by this callback
132+
rx_handle[i] = st20_rx_create(dev_handle, &ops_rx);
133+
if (!rx_handle[i]) {
134+
printf(" rx_session is not correctly created");
135+
free(app[i]);
136+
return -1;
137+
}
138+
app[i]->handle = rx_handle[i];
139+
app[i]->consumer_frame_idx = -1;
140+
app[i]->ready_frame_idx = 0;
141+
app[i]->stop = false;
142+
pthread_mutex_init(&app[i]->wake_mutex, NULL);
143+
pthread_cond_init(&app[i]->wake_cond, NULL);
144+
ret = pthread_create(&app[i]->app_thread, NULL, app_rx_video_frame_thread, app[i]);
145+
if (ret < 0) {
146+
printf("%s(%d), app_thread create fail %d\n", __func__, ret, i);
147+
ret = st20_rx_free(rx_handle[i]);
148+
if (ret) {
149+
printf("session free failed\n");
150+
}
151+
free(app[i]);
152+
return -1;
153+
}
154+
}
155+
// start rx
156+
ret = st_start(dev_handle);
157+
// rx run 120s
158+
sleep(120);
159+
// stop app thread
160+
for (int i = 0; i < session_num; i++) {
161+
app[i]->stop = true;
162+
pthread_join(app[i]->app_thread, NULL);
163+
}
164+
165+
// stop rx
166+
ret = st_stop(dev_handle);
167+
168+
// release session
169+
for (int i = 0; i < session_num; i++) {
170+
ret = st20_rx_free(rx_handle[i]);
171+
if (ret) {
172+
printf("session free failed\n");
173+
}
174+
pthread_mutex_destroy(&app[i]->wake_mutex);
175+
pthread_cond_destroy(&app[i]->wake_cond);
176+
free(app[i]);
177+
}
178+
179+
// destroy device
180+
st_uninit(dev_handle);
181+
return 0;
182+
}

0 commit comments

Comments
 (0)