├── .gitignore
├── LICENSE
├── README.md
├── audio_sink
├── inc
│ └── sx_audio_sink.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_audio_sink.c
├── common
├── inc
│ ├── sx_pkt.h
│ ├── sx_queue.h
│ ├── sx_system.h
│ ├── sx_thread.h
│ ├── sx_thread_priority.h
│ ├── sx_types.h
│ └── sx_udp.h
├── make
│ └── makefile.std
├── makefile
├── makefile_includes.make
└── src
│ ├── sx_queue.c
│ ├── sx_thread.c
│ └── sx_udp.c
├── desc
├── inc
│ └── sx_desc.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_desc.c
├── env
├── 8188eu.ko
├── README
├── dhcpd.conf
├── interfaces
├── isc-dhcp-server
└── setup.py
├── libs
├── ilclient
│ ├── Makefile
│ ├── ilclient.c
│ ├── ilclient.h
│ ├── ilcore.c
│ └── libilclient.a
└── vgfont
│ ├── Makefile
│ ├── font.c
│ ├── graphics.c
│ ├── graphics_x_private.h
│ ├── libvgfont.a
│ ├── vgfont.h
│ ├── vgft.c
│ └── vgft.h
├── mgmt_audio_decoder
├── inc
│ └── sx_mgmt_audio_decoder.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_audio_decoder.c
├── mgmt_audio_scheduler
├── inc
│ └── sx_mgmt_audio_scheduler.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_audio_scheduler.c
├── mgmt_ctl
├── inc
│ └── sx_mgmt_ctl.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_ctl.c
├── mgmt_data
├── inc
│ └── sx_mgmt_data.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_data.c
├── mgmt_env
├── inc
│ └── sx_mgmt_env.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_env.c
├── mgmt_m2ts_decoder
├── inc
│ └── sx_mgmt_m2ts_decoder.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_m2ts_decoder.c
├── mgmt_sys
├── inc
│ └── sx_mgmt_sys.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_sys.c
├── mgmt_video_decoder
├── inc
│ └── sx_mgmt_video_decoder.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_video_decoder.c
├── mgmt_video_scheduler
├── inc
│ └── sx_mgmt_video_scheduler.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_mgmt_video_scheduler.c
├── pipe
├── inc
│ └── sx_pipe.h
├── makefile
├── makefile_includes.make
└── src
│ └── sx_pipe.c
├── release
└── release.py
├── scripts
├── core_channel.py
├── env.txt
├── graph_generate.txt
├── hostapd
├── hostapd_cli
├── p2p_hostapd.conf
├── piracast.py
├── sink.py
├── util.py
├── wfd.py
├── wpa_0_8.conf
├── wpa_cli
└── wpa_supplicant
├── target
├── makefile
├── makefile_includes.make
└── src
│ └── main.c
└── video_sink
├── inc
└── sx_video_sink.h
├── makefile
├── makefile_includes.make
└── src
└── sx_video_sink.c
/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled files
2 | obj
3 | *.pyc
4 | scripts/core
5 | target/core
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This program is free software: you can redistribute it and/or modify
2 | it under the terms of the GNU General Public License as published by
3 | the Free Software Foundation, either version 3 of the License, or
4 | (at your option) any later version.
5 |
6 | This program is distributed in the hope that it will be useful,
7 | but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | GNU General Public License for more details.
10 |
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Welcome to the Piracast project.
2 | =========
3 | Copyright 2014
4 |
5 |
6 | ### Limitation:
7 | 1. Only works with TP-Link dongle.
8 | 2. No HDCP support (cannot remote Netflix or Google Music).
9 |
10 | ### Install Driver:
11 | 1. uname -r //gives ur rp version number
12 | 2. Based on the rp version number choose ur 8188eu tar file from http://www.raspberrypi.org/forums/viewtopic.php?p=462982#p462982
13 | 3. wget https://dl.dropboxusercontent.com/u/80256631/8188eu-201xyyzz.tar.gz
14 | 4. tar -zxvf 8188eu-201*.tar.gz
15 | 5. sudo cp rtl8188eufw.bin /lib/firmware/rtlwifi //not needed anymore if your operating system is above 3.10.33+
16 | 6. sudo install -p -m 644 8188eu.ko /lib/modules/`uname -r`/kernel/drivers/net/wireless
17 | 7. sudo insmod /lib/modules/3.10.33+/kernel/drivers/net/wireless/8188eu.ko
18 | 8. sudo depmod -a
19 | 9. sudo reboot
20 |
21 |
22 | ### Install DHCP server
23 | 1. sudo apt-get install isc-dhcp-server
24 | 2. sudo cp env/isc-dhcp-server /etc/default
25 | 3. sudo cp env/dhcpd.conf /etc/dhcp/
26 | 4. sudo cp env/interfaces /etc/network/interfaces
27 |
28 | ### Compile the project:
29 | 1. cd target
30 | 2. make core
31 |
32 | ### Reboot after installation is completed:
33 | 1. sudo reboot
34 |
35 | ### To run Piracast:
36 | 1. cd scripts
37 | 2. sudo nice -n -20 ./core &
38 | 3. sudo python piracast.py
39 |
--------------------------------------------------------------------------------
/audio_sink/inc/sx_audio_sink.h:
--------------------------------------------------------------------------------
1 | #if !defined(AUDIO_SINK_H)
2 | #define AUDIO_SINK_H
3 |
4 | extern void sx_audio_sink_init(
5 | void
6 | );
7 |
8 | extern UINT8 * sx_audio_sink_buffer_get(
9 | void
10 | );
11 |
12 | extern unsigned int sx_audio_sink_ms_left_get(
13 | void
14 | );
15 |
16 | extern void sx_audio_sink_buffer_set(
17 | unsigned char *buf,
18 | unsigned int buf_len
19 | );
20 |
21 | extern void sx_audio_sink_playback_speed_inc(
22 | void
23 | );
24 |
25 | extern void sx_audio_sink_playback_speed_reset(
26 | void
27 | );
28 |
29 | extern void sx_audio_sink_playback_speed_dec(
30 | void
31 | );
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/audio_sink/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
8 |
--------------------------------------------------------------------------------
/audio_sink/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common mgmt_data video_decoder_hw
2 |
3 | DEP_OBJ := video_decoder_hw
4 |
--------------------------------------------------------------------------------
/common/inc/sx_pkt.h:
--------------------------------------------------------------------------------
1 | #if !defined(PI_PORTAL_PKT)
2 | #define PI_PORTAL_PKT
3 |
4 | #include "sx_types.h"
5 |
6 | #define PID_GET(hdr) ((((hdr).tei_pusi_tp_pid1 & 0x1F) << 8) | (hdr).pid2)
7 | #define CC_GET(hdr) ((hdr).tsc_afc_cc & 0x0F)
8 | #define PUSI_GET(hdr) (((hdr).tei_pusi_tp_pid1 & 0x40) >> 6)
9 | #define AFC_GET(hdr) (((hdr).tsc_afc_cc & 0x30) >> 4)
10 |
11 | #define PIRACAST_PKT_HDR_SIZE (sizeof(unsigned int))
12 | #define PIRACAST_PKT_PAYLOAD_SIZE_MAX (1472-PIRACAST_PKT_HDR_SIZE)
13 |
14 | // --------------------------------------------------------
15 | // sRTP_HDR
16 | // RTP header
17 | //
18 | typedef struct
19 | {
20 | UINT8 version_p_x_cc;
21 | UINT8 m_pt;
22 | UINT16 sequence_num;
23 | UINT32 timestamp;
24 | UINT32 ssrc_id;
25 |
26 | } sRTP_HDR;
27 |
28 |
29 | // --------------------------------------------------------
30 | // sMPEG2_TS_HDR
31 | // MPEG2 Transport Stream header
32 | //
33 | typedef struct
34 | {
35 | UINT8 sync_byte; ///< Sync byte
36 | UINT8 tei_pusi_tp_pid1; ///< Transport Error Indicate (1 bit)
37 | ///< Payload Unit Start Indicator (1 bit)
38 | ///< Transport Priority (1 bit)
39 | ///< PID (first half, 5 bit)
40 | UINT8 pid2; ///< PID (second half, 8 bit)
41 | UINT8 tsc_afc_cc; ///< Transport scrambling control (2 bits)
42 | ///< Adaption Field Control (2 bits)
43 | ///< Continuity Counter (4 bits)
44 |
45 | } sMPEG2_TS_HDR;
46 |
47 |
48 | // --------------------------------------------------------
49 | // sMPEG2_TS_PAYLOAD
50 | // MPEG2 Transport Stream Payload
51 | //
52 | typedef struct
53 | {
54 | UINT8 payload[184];
55 |
56 | } sMPEG2_TS_PAYLOAD;
57 |
58 |
59 | // --------------------------------------------------------
60 | // sMPEG2_TS
61 | // MPEG2 Transport Stream
62 | //
63 | typedef struct
64 | {
65 | sMPEG2_TS_HDR hdr;
66 | sMPEG2_TS_PAYLOAD payload;
67 |
68 | } sMPEG2_TS;
69 |
70 |
71 | typedef struct
72 | {
73 | UINT8 prefix1;
74 | UINT8 prefix2;
75 | UINT8 prefix3;
76 | UINT8 stream;
77 |
78 | } sPES;
79 |
80 |
81 | typedef struct
82 | {
83 | UINT16 length;
84 | UINT8 flag1;
85 | UINT8 flag2;
86 |
87 | } sPES_EXT;
88 |
89 |
90 | typedef struct
91 | {
92 | UINT8 hdr_len;
93 |
94 | } sPES_EXT2;
95 |
96 |
97 | typedef struct
98 | {
99 | unsigned int hdr;
100 | unsigned char payload[PIRACAST_PKT_PAYLOAD_SIZE_MAX];
101 |
102 | } sPI_PORTAL_PKT;
103 |
104 |
105 | #define SLICE_TYPE_PCR 0
106 | #define SLICE_TYPE_SLICE 1
107 |
108 | typedef struct
109 | {
110 | UINT8 type;
111 | UINT8 rsvd[3];
112 | UINT64 timestamp;
113 |
114 | } sSLICE_HDR;
115 |
116 | #endif
117 |
--------------------------------------------------------------------------------
/common/inc/sx_queue.h:
--------------------------------------------------------------------------------
1 | #if !defined(_SX_QUEUE_H_)
2 | #define _SX_QUEUE_H_
3 |
4 | #define SX_QUEUE void *
5 |
6 | extern SX_QUEUE sx_queue_create(
7 | void
8 | );
9 |
10 | extern void sx_queue_destroy(
11 | SX_QUEUE queue
12 | );
13 |
14 | extern void sx_queue_push(
15 | SX_QUEUE queue,
16 | void *data
17 | );
18 |
19 | extern void * sx_queue_pull(
20 | SX_QUEUE queue
21 | );
22 |
23 | extern unsigned int sx_queue_len_get(
24 | SX_QUEUE queue_id
25 | );
26 |
27 | #endif // _SX_QUEUE_H_
28 |
--------------------------------------------------------------------------------
/common/inc/sx_system.h:
--------------------------------------------------------------------------------
1 | #if !defined(_SX_SYSTEM_H_)
2 | #define _SX_SYSTEM_H_
3 |
4 | #define SX_SYSTEM_DELAY_MS (100)
5 | #define SX_SYSTEM_AUDIO_SOURCE_DELAY_MS (400)
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/common/inc/sx_thread.h:
--------------------------------------------------------------------------------
1 | #if !defined(_RT_THREAD_H_)
2 | #define _RT_THREAD_H_
3 |
4 | #include "sx_thread_priority.h"
5 |
6 | extern void sx_thread_create(
7 | void *thread_id,
8 | void *thread_func,
9 | void *thread_arg,
10 | unsigned int thread_priority
11 | );
12 |
13 | #endif // #if !defined(_RT_THREAD_H_)
14 |
--------------------------------------------------------------------------------
/common/inc/sx_thread_priority.h:
--------------------------------------------------------------------------------
1 | #if !defined(_SX_THREAD_PRIORITY_H_)
2 | #define _SX_THREAD_PRIORITY_H_
3 |
4 | // The priority also depicts the data flow:
5 | //
6 | // -> VIDEO_DECODER -> VIDEO_SCHEDULE
7 | // PKT_RX -> M2TS_DEMUX -|
8 | // -> AUDIO_DECODER -> AUDIO_SCHEDULE
9 | //
10 | // Application profiling reveals audio decoding requires much more processing
11 | // because of the endianness swap on the received data, thus audio processing
12 | // threads need to run at lower priority than video to prevent video jittering.
13 | // Audio is also buffered by hardware; thus minor jitter will not affect
14 | // playback.
15 |
16 | #define MGMT_DATA_RX_THREAD_PRIORITY 90
17 | #define MGMT_M2TS_PKT_PROCESS_THREAD_PRIORITY 80
18 | #define VIDEO_DECODER_THREAD_PRIORITY 70
19 | #define VIDEO_SCHEDULER_THREAD_PRIORITY 70
20 | #define MGMT_AUDIO_DECODER_THREAD_PRIORITY 60
21 | #define MGMT_AUDIO_SCHEDULER_THREAD_PRIORITY 60
22 | #define MGMT_SYS_THREAD_PRIORITY 50
23 |
24 | #endif // #if !defined(_SX_THREAD_PRIORITY_H_)
25 |
--------------------------------------------------------------------------------
/common/inc/sx_types.h:
--------------------------------------------------------------------------------
1 | #if !defined(_SX_TYPES_H_)
2 | #define _SX_TYPES_H_
3 |
4 | #define UINT8 unsigned char
5 | #define UINT16 unsigned short
6 | #define UINT32 unsigned int
7 | #define INT32 signed int
8 | #define UINT64 unsigned long long
9 | #define INT64 signed long long
10 |
11 | #endif // _SX_TYPES_H_
12 |
--------------------------------------------------------------------------------
/common/inc/sx_udp.h:
--------------------------------------------------------------------------------
1 | #if !defined(_UDP_SOCKET_H_)
2 | #define _UDP_SOCKET_H_
3 |
4 | #define SBOX_UDP_ID void *
5 |
6 | extern void * sx_udp_create(
7 | unsigned short local_port
8 | );
9 |
10 | extern void sx_udp_send(
11 | SBOX_UDP_ID id,
12 | unsigned char *pkt,
13 | unsigned int pkt_len
14 | );
15 |
16 | extern void sx_udp_recv(
17 | SBOX_UDP_ID id,
18 | char *pkt,
19 | unsigned int *pkt_len
20 | );
21 |
22 | #endif // #if !defined(_UDP_SOCKET_H_)
23 |
--------------------------------------------------------------------------------
/common/make/makefile.std:
--------------------------------------------------------------------------------
1 | MODULE_DIR := .
2 |
3 | include $(MODULE_DIR)/makefile_includes.make
4 |
5 | MODULE_INC := $(MODULE_DIR)/inc
6 | MODULE_SRC := $(MODULE_DIR)/src
7 | MODULE_OBJ := $(MODULE_DIR)/obj
8 |
9 | obj_dir := obj
10 |
11 | DEP_INCLUDES := $(foreach depModule, $(DEP_INC), $(addprefix -I, $(sort $(dir $(wildcard $(PLATFORM_ROOT)/$(depModule)/inc/*.h)))))
12 |
13 | SYS_INCLUDES := -I $(SDKSTAGE)/opt/vc/include \
14 | -I $(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads \
15 | -I $(SDKSTAGE)/opt/vc/include/interface/vmcs_host/linux \
16 | -I $(PLATFORM_ROOT)/libs/ilclient \
17 | -I $(PLATFORM_ROOT)/libs/vgfont
18 |
19 | MODULE_INCLUDES := -I $(MODULE_INC)
20 |
21 | INCLUDES := $(MODULE_INCLUDES) \
22 | $(DEP_INCLUDES) \
23 | $(SYS_INCLUDES)
24 |
25 | module_dep_include_paths := $(foreach depModule, $(DEP_INC), $(sort $(dir $(wildcard $(PLATFORM_ROOT)/$(depModule)/inc/*.h))))
26 | module_dep_includes := $(foreach depIncludePath, $(module_dep_include_paths), $(notdir $(wildcard $(depIncludePath)/*.h)))
27 |
28 | vpath %.c $(MODULE_SRC)
29 | vpath %.h $(MODULE_INC):$(foreach depIncludePath, $(module_dep_include_paths), $(addprefix :, $(depIncludePath)))
30 |
31 | temp_depend_objs := $(addprefix $(PLATFORM_ROOT)/, $(DEP_OBJ))
32 |
33 | depend_objs := $(foreach depModule, $(temp_depend_objs), $(strip $(wildcard $(depModule))))
34 |
35 | depend_objects := $(foreach depModule, $(depend_objs), $(depModule)/$(obj_dir)/module_$(notdir $(depModule)).o)
36 |
37 | # define modules sources (%.c)
38 | module_sources := $(notdir $(wildcard $(MODULE_SRC)/*.c))
39 |
40 | # define modules objects (%.o)
41 | module_objects := $(addprefix $(MODULE_OBJ)/, $(module_sources:.c=.o))
42 |
43 | # define module object (module_%.o)
44 | module_object := $(MODULE_OBJ)/module_$(notdir $(CURDIR)).o
45 |
46 | ifeq ($(strip $(wildcard $(MODULE_OBJ))),)
47 | module_mkdirs := mkdir_obj
48 | endif
49 |
50 | app_executable := $(obj_dir)/app
51 |
52 | # Dependent object target.
53 | .PHONY : $(depend_objects)
54 | $(depend_objects) :
55 | make -C $(subst /$(obj_dir),,$(dir $@)) all
56 |
57 | LIBDIR := -L $(PLATFORM_ROOT)/libs/ilclient \
58 | -L $(PLATFORM_ROOT)/libs/vgfont \
59 | -L /opt/vc/lib/
60 |
61 | # Linker options.
62 | LDFLAGS := -l ilclient -l pthread -l rt -l bcm_host -l vcos -l openmaxil
63 | LDFLAGS += -pg
64 |
65 | # Compile options.
66 | CFLAGS := -pg -g
67 |
68 | # Default build target. This is the recursive build target. The make script
69 | # enters every directory and issues "make", which defaults to "make all".
70 | all : $(module_mkdirs) \
71 | $(module_object)
72 |
73 | core : $(depend_objects)
74 | $(CC) $^ $(LIBDIR) $(LDFLAGS) -o $@
75 | cp $@ ../scripts
76 |
77 | # Create output directory.
78 | mkdir_obj :
79 | mkdir $(MODULE_OBJ)
80 |
81 | # Link all compiled .o files into a single module .o file.
82 | $(module_object) : $(module_objects)
83 | $(LD) -r $^ -o $@
84 |
85 | # Compile all source .c files to .o files.
86 | $(MODULE_OBJ)/%.o : %.c $(module_dep_includes)
87 | $(CC) -c $(CFLAGS) $(INCLUDES) $< -o $@
88 |
89 | # Remove all object files.
90 | clobber_mod_files := $(module_object) \
91 | $(module_objects) \
92 | $(app_executable)
93 |
94 | clean:
95 | rm -rf $(obj_dir)
96 |
97 | clobber : clobber_dependents
98 | rm -f $(clobber_mod_files)
99 |
100 | clobber_dependent_cmd := $(foreach depModule, $(depend_objs), make -C $(depModule) clobber;)
101 |
102 | ifeq (${MAKELEVEL},0)
103 | clobber_dependents :
104 | $(clobber_dependent_cmd)
105 | else
106 | clobber_dependents :
107 | endif
108 |
109 |
--------------------------------------------------------------------------------
/common/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/common/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/common/src/sx_queue.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "sx_types.h"
8 | #include "sx_queue.h"
9 |
10 | typedef struct sNODE
11 | {
12 | struct sNODE *next;
13 | void *data;
14 |
15 | } sNODE;
16 |
17 |
18 | typedef struct
19 | {
20 | sNODE *head;
21 | sNODE *tail;
22 | pthread_mutex_t lock;
23 | sem_t sem;
24 | unsigned int len;
25 | UINT32 high_water_mark;
26 |
27 | } sQUEUE;
28 |
29 |
30 | // --------------------------------------------------------
31 | // rt_queue_create
32 | // Create a queue.
33 | //
34 | SX_QUEUE sx_queue_create(
35 | void
36 | )
37 | {
38 | sQUEUE *queue = malloc(sizeof(sQUEUE));
39 |
40 | pthread_mutex_init(&queue->lock, NULL);
41 |
42 | sem_init(&queue->sem, 0, 0);
43 |
44 | queue->head = NULL;
45 | queue->tail = NULL;
46 | queue->len = 0;
47 |
48 | return queue;
49 | }
50 |
51 |
52 | // --------------------------------------------------------
53 | // rt_queue_destroy
54 | // Destory a queue.
55 | //
56 | void sx_queue_destroy(
57 | SX_QUEUE queue_id
58 | )
59 | {
60 | sQUEUE *queue;
61 | sNODE *curr;
62 | sNODE *next;
63 |
64 |
65 | // Get the queue.
66 | queue = queue_id;
67 |
68 | // Free every node.
69 | curr = queue->head;
70 | while(curr)
71 | {
72 | next = curr->next;
73 |
74 | // Free data.
75 | free(curr->data);
76 |
77 | // Free node.
78 | free(curr);
79 |
80 | curr = next;
81 | }
82 |
83 | // Destroy mutex.
84 | pthread_mutex_destroy(&queue->lock);
85 |
86 | // Free queue.
87 | free(queue);
88 | }
89 |
90 |
91 | // --------------------------------------------------------
92 | // rt_queue_push
93 | // Push a data payload.
94 | //
95 | void sx_queue_push(
96 | SX_QUEUE queue_id,
97 | void *data
98 | )
99 | {
100 | sNODE *node;
101 | sQUEUE *queue;
102 |
103 |
104 | assert(data != NULL);
105 |
106 | // Get queue.
107 | queue = queue_id;
108 |
109 | // Construct new node.
110 | node = malloc(sizeof(sNODE));
111 | node->data = data;
112 | node->next = NULL;
113 |
114 | // Lock.
115 | pthread_mutex_lock(&queue->lock);
116 |
117 | #if 0
118 | printf("(rt_queue): push(): id = 0x%x, len = %d\n",
119 | (int) queue_id,
120 | queue->len);
121 | #endif
122 |
123 | // Is list empty?
124 | if(queue->head == NULL)
125 | {
126 | // List is empty, insert only node.
127 | queue->head = node;
128 |
129 | queue->tail = node;
130 |
131 | goto cleanup;
132 | }
133 |
134 | // Append to end.
135 | queue->tail->next = node;
136 |
137 | // Update tail.
138 | queue->tail = node;
139 |
140 | cleanup:
141 |
142 | queue->len++;
143 |
144 | // if(queue->len > queue->high_water_mark)
145 | // {
146 | // printf("(rt_queue): push(): id = 0x%x, len = %d\n",
147 | // queue_id,
148 | // queue->len);
149 | //
150 | // queue->high_water_mark = queue->len;
151 | // }
152 |
153 | pthread_mutex_unlock(&queue->lock);
154 |
155 | // sem_post(&queue->sem);
156 | }
157 |
158 |
159 | // --------------------------------------------------------
160 | // rt_queue_pull
161 | // Pull a data payload.
162 | //
163 | void * sx_queue_pull(
164 | SX_QUEUE queue_id
165 | )
166 | {
167 | sQUEUE *queue;
168 | unsigned char *data;
169 |
170 |
171 | // Get queue.
172 | queue = queue_id;
173 |
174 | // sem_wait(&queue->sem);
175 |
176 | // Lock.
177 | pthread_mutex_lock(&queue->lock);
178 |
179 | #if 0
180 | printf("(rt_queue): pull(): id = 0x%x, len = %d\n",
181 | (int) queue,
182 | queue->len);
183 | #endif
184 |
185 | // Is list empty?
186 | if(queue->head == NULL)
187 | {
188 | assert(queue->tail == NULL);
189 |
190 | // List is empty.
191 | data = NULL;
192 |
193 | goto cleanup;
194 | }
195 |
196 | if(queue->head == queue->tail)
197 | {
198 | assert(queue->head->next == NULL);
199 | assert(queue->tail->next == NULL);
200 |
201 | // List only has one element.
202 | data = queue->head->data;
203 |
204 | // Free the node.
205 | free(queue->head);
206 |
207 | // Reset head and tail.
208 | queue->head = NULL;
209 | queue->tail = NULL;
210 |
211 | goto cleanup;
212 | }
213 |
214 | // More than one element.
215 |
216 | // Return packet.
217 | data = queue->head->data;
218 |
219 | // Get next.
220 | sNODE *next = queue->head->next;
221 |
222 | // Free head.
223 | free(queue->head);
224 |
225 | // Advance head.
226 | queue->head = next;
227 |
228 | cleanup:
229 |
230 | if(data != NULL)
231 | {
232 | queue->len--;
233 | }
234 |
235 | pthread_mutex_unlock(&queue->lock);
236 |
237 | return data;
238 | }
239 |
240 |
241 | unsigned int sx_queue_len_get(
242 | SX_QUEUE queue_id
243 | )
244 | {
245 | sQUEUE *queue;
246 | unsigned int len;
247 |
248 |
249 | // Get queue.
250 | queue = queue_id;
251 |
252 | pthread_mutex_lock(&queue->lock);
253 |
254 | len = queue->len;
255 |
256 | pthread_mutex_unlock(&queue->lock);
257 |
258 | return len;
259 | }
260 |
--------------------------------------------------------------------------------
/common/src/sx_thread.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | void sx_thread_create(
7 | void *thread_id,
8 | void *thread_func,
9 | void *thread_arg,
10 | unsigned int thread_priority
11 | )
12 | {
13 | struct sched_param param;
14 |
15 |
16 | // Create decoder thread.
17 | pthread_create(thread_id, NULL, (void *) thread_func, NULL);
18 |
19 | // Set thread priority.
20 | // Launch the program using sudo to honor the priority setting!
21 | memset(¶m, 0, sizeof(param));
22 | param.sched_priority = thread_priority;
23 | pthread_setschedparam(*((int *) thread_id), SCHED_FIFO, ¶m);
24 | }
25 |
--------------------------------------------------------------------------------
/common/src/sx_udp.c:
--------------------------------------------------------------------------------
1 | // Includes
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "sx_types.h"
12 | #include "sx_udp.h"
13 |
14 | typedef struct
15 | {
16 | unsigned int peer_ip;
17 | unsigned short peer_port;
18 | unsigned int local_ip;
19 | unsigned short local_port;
20 |
21 | int sock;
22 |
23 | } sUDP_CBLK;
24 |
25 |
26 | void * sx_udp_create(
27 | UINT16 port
28 | )
29 | {
30 | struct sockaddr_in client_addr;
31 | int rv;
32 |
33 |
34 | sUDP_CBLK *udp_cblk = malloc(sizeof(sUDP_CBLK));
35 |
36 | memset(udp_cblk, 0, sizeof(sUDP_CBLK));
37 |
38 | // Create socket.
39 | udp_cblk->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
40 | assert(udp_cblk->sock != -1);
41 |
42 | #if 0
43 | char *opt;
44 | opt = "wlan0";
45 | rv = setsockopt(udp_cblk->sock, SOL_SOCKET, SO_BINDTODEVICE, opt, 5);
46 | assert(rv == 0);
47 | #endif
48 |
49 | // Listen to anyone that talks to us on the right port.
50 | client_addr.sin_family = AF_INET;
51 | client_addr.sin_port = htons(port);
52 | client_addr.sin_addr.s_addr = INADDR_ANY;
53 | bzero(&(client_addr.sin_zero), 8);
54 |
55 | // Bind to address.
56 | rv = bind(udp_cblk->sock,
57 | (struct sockaddr *) &client_addr,
58 | sizeof(client_addr));
59 | if(rv < 0)
60 | {
61 | // printf("(udp): udp_socket_create(): rv = %d, errno %s\n", rc, strerror(errno));
62 | assert(0);
63 | }
64 |
65 | return udp_cblk;
66 | }
67 |
68 |
69 | void sx_udp_recv(
70 | SBOX_UDP_ID id,
71 | char *pkt,
72 | unsigned int *pkt_len
73 | )
74 | {
75 | struct sockaddr_in server_addr;
76 | unsigned int bytes_read;
77 | unsigned int addr_len;
78 | sUDP_CBLK *udp_cblk = id;
79 |
80 |
81 | #if 0
82 | printf("(udp): udp_socket_recv(): ID = 0x%x\n", id);
83 | #endif
84 |
85 | addr_len = sizeof(struct sockaddr);
86 | // printf("(udp): pkt = 0x%x, pkt_len = %d\n", pkt, *pkt_len);
87 | // printf("(udp): before\n");
88 | bytes_read = recvfrom(udp_cblk->sock,
89 | pkt,
90 | *pkt_len,
91 | 0,
92 | (struct sockaddr *) &server_addr,
93 | &addr_len);
94 | // printf("(udp): after\n");
95 | if(bytes_read <= 0)
96 | {
97 | #if 0
98 | printf("(udp): udp_socket_recv(): error = %d\n", bytes_read);
99 | #endif
100 | assert(0);
101 | }
102 |
103 | #if 0
104 | printf("(udp): udp_socket_recv()\n");
105 | #endif
106 |
107 | *pkt_len = bytes_read;
108 | }
109 |
110 |
111 | void sx_udp_destroy(
112 | SBOX_UDP_ID id
113 | )
114 | {
115 | // TODO:
116 | }
117 |
--------------------------------------------------------------------------------
/desc/inc/sx_desc.h:
--------------------------------------------------------------------------------
1 | #if !defined(_SX_DESC_H_)
2 | #define _SX_DESC_H_
3 |
4 | #include "sx_types.h"
5 |
6 | typedef struct sSX_DESC
7 | {
8 | UINT8 *data;
9 | UINT32 data_len;
10 | struct sSX_DESC *next;
11 |
12 | } sSX_DESC;
13 |
14 | extern sSX_DESC * sx_desc_get(
15 | void
16 | );
17 |
18 | extern void sx_desc_put(
19 | sSX_DESC *desc
20 | );
21 |
22 | #endif // _SX_DESC_H_
23 |
--------------------------------------------------------------------------------
/desc/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/desc/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/desc/src/sx_desc.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "sx_desc.h"
5 |
6 | // --------------------------------------------------------
7 | // sx_desc_get
8 | // Gets a descriptor
9 | //
10 | sSX_DESC * sx_desc_get(
11 | void
12 | )
13 | {
14 | sSX_DESC *desc = malloc(sizeof(sSX_DESC));
15 | assert(desc != NULL);
16 |
17 | desc->data = NULL;
18 | desc->data_len = 0;
19 | desc->next = NULL;
20 |
21 | return desc;
22 | }
23 |
24 |
25 | // --------------------------------------------------------
26 | // sx_desc_put
27 | // Frees a descriptor (or a descriptor chain)
28 | //
29 | void sx_desc_put(
30 | sSX_DESC *desc
31 | )
32 | {
33 | sSX_DESC *curr;
34 | sSX_DESC *next;
35 |
36 |
37 | // Consistency check.
38 | assert(desc != NULL);
39 |
40 | // Initialize current.
41 | curr = desc;
42 |
43 | // Release descriptors and data.
44 | while(curr != NULL)
45 | {
46 | next = curr->next;
47 |
48 | free(curr->data);
49 | free(curr);
50 |
51 | curr = next;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/env/8188eu.ko:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemonkeyricky/piracast/04a0d2b6bec6c408ef41d872034333903f6fabe5/env/8188eu.ko
--------------------------------------------------------------------------------
/env/README:
--------------------------------------------------------------------------------
1 | Thank you for using Piracast. Note that this is EXTREMELY early beta and the
2 | environment has not been finalized.
3 |
4 | To get started:
5 |
6 | 1. cd into install directory and execute the setup script.
7 | cd install
8 | sudo python setup.py
9 | 2. Set static IP address on wlan0 interface as per setup script instruction.
10 | 3. Reboot.
11 | 4. To execute the application:
12 | cd application
13 | sudo ./main
14 | 5. You should now see Piracast as an available Wireless Display on your Android phone/tablet.
15 |
--------------------------------------------------------------------------------
/env/dhcpd.conf:
--------------------------------------------------------------------------------
1 | # dhcpd.conf
2 | #
3 | # Sample configuration file for ISC dhcpd
4 | #
5 |
6 | # option definitions common to all supported networks...
7 | option domain-name "example.org";
8 | option domain-name-servers ns1.example.org, ns2.example.org;
9 |
10 | default-lease-time 600;
11 | max-lease-time 7200;
12 |
13 | # Use this to enble / disable dynamic dns updates globally.
14 | #ddns-update-style none;
15 |
16 | # If this DHCP server is the official DHCP server for the local
17 | # network, the authoritative directive should be uncommented.
18 | #authoritative;
19 |
20 | # Use this to send dhcp log messages to a different log file (you also
21 | # have to hack syslog.conf to complete the redirection).
22 | log-facility local7;
23 |
24 | # No service will be given on this subnet, but declaring it helps the
25 | # DHCP server to understand the network topology.
26 |
27 | subnet 10.152.187.0 netmask 255.255.255.0 {
28 | }
29 |
30 | # This is a very basic subnet declaration.
31 |
32 | subnet 10.254.239.0 netmask 255.255.255.224 {
33 | range 10.254.239.10 10.254.239.20;
34 | option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
35 | }
36 |
37 | # This declaration allows BOOTP clients to get dynamic addresses,
38 | # which we don't really recommend.
39 |
40 | subnet 10.254.239.32 netmask 255.255.255.224 {
41 | range dynamic-bootp 10.254.239.40 10.254.239.60;
42 | option broadcast-address 10.254.239.31;
43 | option routers rtr-239-32-1.example.org;
44 | }
45 |
46 | # A slightly different configuration for an internal subnet.
47 | subnet 192.168.2.0 netmask 255.255.255.0 {
48 | range 192.168.2.30 192.168.2.150;
49 | option domain-name-servers 192.168.2.254;
50 | option domain-name "internal.org";
51 | option routers 192.168.2.254;
52 | option broadcast-address 192.168.2.255;
53 | default-lease-time 6000;
54 | max-lease-time 7200;
55 | }
56 |
57 | subnet 172.21.69.0 netmask 255.255.255.0 {
58 |
59 | }
60 |
61 | # Hosts which require special configuration options can be listed in
62 | # host statements. If no address is specified, the address will be
63 | # allocated dynamically (if possible), but the host-specific information
64 | # will still come from the host declaration.
65 |
66 | host passacaglia {
67 | hardware ethernet 0:0:c0:5d:bd:95;
68 | filename "vmunix.passacaglia";
69 | server-name "toccata.fugue.com";
70 | }
71 |
72 | # Fixed IP addresses can also be specified for hosts. These addresses
73 | # should not also be listed as being available for dynamic assignment.
74 | # Hosts for which fixed IP addresses have been specified can boot using
75 | # BOOTP or DHCP. Hosts for which no fixed address is specified can only
76 | # be booted with DHCP, unless there is an address range on the subnet
77 | # to which a BOOTP client is connected which has the dynamic-bootp flag
78 | # set.
79 | host fantasia {
80 | hardware ethernet 08:00:07:26:c0:a5;
81 | fixed-address fantasia.fugue.com;
82 | }
83 |
84 | # You can declare a class of clients and then do address allocation
85 | # based on that. The example below shows a case where all clients
86 | # in a certain class get addresses on the 10.17.224/24 subnet, and all
87 | # other clients get addresses on the 10.0.29/24 subnet.
88 |
89 | class "foo" {
90 | match if substring (option vendor-class-identifier, 0, 4) = "SUNW";
91 | }
92 |
93 | shared-network 224-29 {
94 | subnet 10.17.224.0 netmask 255.255.255.0 {
95 | option routers rtr-224.example.org;
96 | }
97 | subnet 10.0.29.0 netmask 255.255.255.0 {
98 | option routers rtr-29.example.org;
99 | }
100 | pool {
101 | allow members of "foo";
102 | range 10.17.224.10 10.17.224.250;
103 | }
104 | pool {
105 | deny members of "foo";
106 | range 10.0.29.10 10.0.29.230;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/env/interfaces:
--------------------------------------------------------------------------------
1 | auto lo
2 |
3 | iface lo inet loopback
4 | iface eth0 inet dhcp
5 |
6 | allow-hotplug wlan0
7 | iface wlan0 inet static
8 | address 192.168.2.254
9 | netmask 255.255.255.0
10 | gateway 192.168.2.254
11 |
--------------------------------------------------------------------------------
/env/isc-dhcp-server:
--------------------------------------------------------------------------------
1 | # Defaults for isc-dhcp-server initscript
2 | # sourced by /etc/init.d/isc-dhcp-server
3 | # installed at /etc/default/isc-dhcp-server by the maintainer scripts
4 |
5 | #
6 | # This is a POSIX shell fragment
7 | #
8 |
9 | # Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
10 | #DHCPD_CONF=/etc/dhcp/dhcpd.conf
11 |
12 | # Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
13 | #DHCPD_PID=/var/run/dhcpd.pid
14 |
15 | # Additional options to start dhcpd with.
16 | # Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
17 | #OPTIONS=""
18 |
19 | # On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
20 | # Separate multiple interfaces with spaces, e.g. "eth0 eth1".
21 | INTERFACES="wlan0"
22 |
--------------------------------------------------------------------------------
/env/setup.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | print 'Installing wireless driver...'
4 | cmd_copy_driver = 'cp 8188eu.ko /lib/modules/`uname -r`/kernel/drivers/net/wireless'
5 | os.system(cmd_copy_driver)
6 | os.system('depmod -a')
7 | os.system('modprobe 8188eu')
8 |
9 | print 'Installing DHCP server...'
10 | cmd_apt_get_update = 'sudo apt-get update'
11 | cmd_install_dhcp = 'sudo apt-get install isc-dhcp-server'
12 | os.system(cmd_apt_get_update)
13 | os.system(cmd_install_dhcp)
14 |
15 | print 'Overwriting isc-dhcp-server ...'
16 | cmd_copy_dhcp_server = 'cp isc-dhcp-server /etc/default/'
17 | os.system(cmd_copy_dhcp_server)
18 |
19 | print 'Overwriting dhcpd.conf ...'
20 | cmd_copy_dhcp_server = 'cp dhcpd.conf /etc/dhcp/'
21 | os.system(cmd_copy_dhcp_server)
22 |
23 | print 'Overwriting network interface file (interfaces) ...'
24 | cmd_copy_interfaces = 'cp interfaces /etc/network/'
25 | os.system(cmd_copy_interfaces)
26 |
27 | print 'Enable execute permission executables...'
28 |
29 | executables = ['../application/hostapd',
30 | '../application/hostapd_cli',
31 | '../application/wpa_cli',
32 | '../application/wpa_supplicant',
33 | '../application/app']
34 |
35 | for executable in executables :
36 | enable_add_permission_cmd = 'chmod 777 ' + executable
37 | os.system(enable_add_permission_cmd)
38 |
39 | print ''
40 | print ''
41 | print ''
42 |
43 | print 'Installation is completed. Please restart your Pi.'
44 | print ''
45 | print 'To launch the application after restart:'
46 | print ' 1. cd piracast/application'
47 | print ' 1. sudo ./main'
48 | print ''
49 |
--------------------------------------------------------------------------------
/libs/ilclient/Makefile:
--------------------------------------------------------------------------------
1 | OBJS=ilclient.o ilcore.o
2 | LIB=libilclient.a
3 |
4 | include ../../Makefile.include
5 |
6 |
--------------------------------------------------------------------------------
/libs/ilclient/ilcore.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012, Broadcom Europe Ltd
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of the copyright holder nor the
13 | names of its contributors may be used to endorse or promote products
14 | derived from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | /*
29 | * \file
30 | *
31 | * \brief Host core implementation.
32 | */
33 |
34 | #include
35 | #include
36 |
37 | //includes
38 | #include
39 | #include
40 | #include
41 | #include
42 |
43 | #include "IL/OMX_Component.h"
44 | #include "interface/vcos/vcos.h"
45 |
46 | #include "interface/vmcs_host/vcilcs.h"
47 | #include "interface/vmcs_host/vchost.h"
48 | #include "interface/vmcs_host/vcilcs_common.h"
49 |
50 | static int coreInit = 0;
51 | static int nActiveHandles = 0;
52 | static ILCS_SERVICE_T *ilcs_service = NULL;
53 | static VCOS_MUTEX_T lock;
54 | static VCOS_ONCE_T once = VCOS_ONCE_INIT;
55 |
56 | /* Atomic creation of lock protecting shared state */
57 | static void initOnce(void)
58 | {
59 | VCOS_STATUS_T status;
60 | status = vcos_mutex_create(&lock, VCOS_FUNCTION);
61 | vcos_demand(status == VCOS_SUCCESS);
62 | }
63 |
64 | /* OMX_Init */
65 | OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void)
66 | {
67 | VCOS_STATUS_T status;
68 | OMX_ERRORTYPE err = OMX_ErrorNone;
69 |
70 | status = vcos_once(&once, initOnce);
71 | vcos_demand(status == VCOS_SUCCESS);
72 |
73 | vcos_mutex_lock(&lock);
74 |
75 | if(coreInit == 0)
76 | {
77 | // we need to connect via an ILCS connection to VideoCore
78 | VCHI_INSTANCE_T initialise_instance;
79 | VCHI_CONNECTION_T *connection;
80 | ILCS_CONFIG_T config;
81 |
82 | vc_host_get_vchi_state(&initialise_instance, &connection);
83 |
84 | vcilcs_config(&config);
85 |
86 | ilcs_service = ilcs_init((VCHIQ_INSTANCE_T) initialise_instance, (void **) &connection, &config, 0);
87 |
88 | if(ilcs_service == NULL)
89 | {
90 | err = OMX_ErrorHardware;
91 | goto end;
92 | }
93 |
94 | coreInit = 1;
95 | }
96 | else
97 | coreInit++;
98 |
99 | end:
100 | vcos_mutex_unlock(&lock);
101 | return err;
102 | }
103 |
104 | /* OMX_Deinit */
105 | OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void)
106 | {
107 | if(coreInit == 0) // || (coreInit == 1 && nActiveHandles > 0))
108 | return OMX_ErrorNotReady;
109 |
110 | vcos_mutex_lock(&lock);
111 |
112 | coreInit--;
113 |
114 | if(coreInit == 0)
115 | {
116 | // we need to teardown the ILCS connection to VideoCore
117 | ilcs_deinit(ilcs_service);
118 | ilcs_service = NULL;
119 | }
120 |
121 | vcos_mutex_unlock(&lock);
122 |
123 | return OMX_ErrorNone;
124 | }
125 |
126 |
127 | /* OMX_ComponentNameEnum */
128 | OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
129 | OMX_OUT OMX_STRING cComponentName,
130 | OMX_IN OMX_U32 nNameLength,
131 | OMX_IN OMX_U32 nIndex)
132 | {
133 | if(ilcs_service == NULL)
134 | return OMX_ErrorBadParameter;
135 |
136 | return vcil_out_component_name_enum(ilcs_get_common(ilcs_service), cComponentName, nNameLength, nIndex);
137 | }
138 |
139 |
140 | /* OMX_GetHandle */
141 | OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
142 | OMX_OUT OMX_HANDLETYPE* pHandle,
143 | OMX_IN OMX_STRING cComponentName,
144 | OMX_IN OMX_PTR pAppData,
145 | OMX_IN OMX_CALLBACKTYPE* pCallBacks)
146 | {
147 | OMX_ERRORTYPE eError;
148 | OMX_COMPONENTTYPE *pComp;
149 | OMX_HANDLETYPE hHandle = 0;
150 |
151 | if (pHandle == NULL || cComponentName == NULL || pCallBacks == NULL || ilcs_service == NULL)
152 | {
153 | if(pHandle)
154 | *pHandle = NULL;
155 | return OMX_ErrorBadParameter;
156 | }
157 |
158 | {
159 | pComp = (OMX_COMPONENTTYPE *)malloc(sizeof(OMX_COMPONENTTYPE));
160 | if (!pComp)
161 | {
162 | vcos_assert(0);
163 | return OMX_ErrorInsufficientResources;
164 | }
165 | memset(pComp, 0, sizeof(OMX_COMPONENTTYPE));
166 | hHandle = (OMX_HANDLETYPE)pComp;
167 | pComp->nSize = sizeof(OMX_COMPONENTTYPE);
168 | pComp->nVersion.nVersion = OMX_VERSION;
169 | eError = vcil_out_create_component(ilcs_get_common(ilcs_service), hHandle, cComponentName);
170 |
171 | if (eError == OMX_ErrorNone) {
172 | // Check that all function pointers have been filled in.
173 | // All fields should be non-zero.
174 | int i;
175 | uint32_t *p = (uint32_t *) pComp;
176 | for(i=0; i>2; i++)
177 | if(*p++ == 0)
178 | eError = OMX_ErrorInvalidComponent;
179 |
180 | if(eError != OMX_ErrorNone && pComp->ComponentDeInit)
181 | pComp->ComponentDeInit(hHandle);
182 | }
183 |
184 | if (eError == OMX_ErrorNone) {
185 | eError = pComp->SetCallbacks(hHandle,pCallBacks,pAppData);
186 | if (eError != OMX_ErrorNone)
187 | pComp->ComponentDeInit(hHandle);
188 | }
189 | if (eError == OMX_ErrorNone) {
190 | *pHandle = hHandle;
191 | }
192 | else {
193 | *pHandle = NULL;
194 | free(pComp);
195 | }
196 | }
197 |
198 | if (eError == OMX_ErrorNone) {
199 | vcos_mutex_lock(&lock);
200 | nActiveHandles++;
201 | vcos_mutex_unlock(&lock);
202 | }
203 |
204 | return eError;
205 | }
206 |
207 | /* OMX_FreeHandle */
208 | OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
209 | OMX_IN OMX_HANDLETYPE hComponent)
210 | {
211 | OMX_ERRORTYPE eError = OMX_ErrorNone;
212 | OMX_COMPONENTTYPE *pComp;
213 |
214 | if (hComponent == NULL || ilcs_service == NULL)
215 | return OMX_ErrorBadParameter;
216 |
217 | pComp = (OMX_COMPONENTTYPE*)hComponent;
218 |
219 | if (ilcs_service == NULL)
220 | return OMX_ErrorBadParameter;
221 |
222 | eError = (pComp->ComponentDeInit)(hComponent);
223 | if (eError == OMX_ErrorNone) {
224 | vcos_mutex_lock(&lock);
225 | --nActiveHandles;
226 | vcos_mutex_unlock(&lock);
227 | free(pComp);
228 | }
229 |
230 | vcos_assert(nActiveHandles >= 0);
231 |
232 | return eError;
233 | }
234 |
235 | /* OMX_SetupTunnel */
236 | OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
237 | OMX_IN OMX_HANDLETYPE hOutput,
238 | OMX_IN OMX_U32 nPortOutput,
239 | OMX_IN OMX_HANDLETYPE hInput,
240 | OMX_IN OMX_U32 nPortInput)
241 | {
242 | OMX_ERRORTYPE eError = OMX_ErrorNone;
243 | OMX_COMPONENTTYPE *pCompIn, *pCompOut;
244 | OMX_TUNNELSETUPTYPE oTunnelSetup;
245 |
246 | if ((hOutput == NULL && hInput == NULL) || ilcs_service == NULL)
247 | return OMX_ErrorBadParameter;
248 |
249 | oTunnelSetup.nTunnelFlags = 0;
250 | oTunnelSetup.eSupplier = OMX_BufferSupplyUnspecified;
251 |
252 | pCompOut = (OMX_COMPONENTTYPE*)hOutput;
253 |
254 | if (hOutput){
255 | eError = pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, hInput, nPortInput, &oTunnelSetup);
256 | }
257 |
258 | if (eError == OMX_ErrorNone && hInput) {
259 | pCompIn = (OMX_COMPONENTTYPE*)hInput;
260 | eError = pCompIn->ComponentTunnelRequest(hInput, nPortInput, hOutput, nPortOutput, &oTunnelSetup);
261 |
262 | if (eError != OMX_ErrorNone && hOutput) {
263 | /* cancel tunnel request on output port since input port failed */
264 | pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, NULL, 0, NULL);
265 | }
266 | }
267 | return eError;
268 | }
269 |
270 | /* OMX_GetComponentsOfRole */
271 | OMX_ERRORTYPE OMX_GetComponentsOfRole (
272 | OMX_IN OMX_STRING role,
273 | OMX_INOUT OMX_U32 *pNumComps,
274 | OMX_INOUT OMX_U8 **compNames)
275 | {
276 | OMX_ERRORTYPE eError = OMX_ErrorNone;
277 |
278 | *pNumComps = 0;
279 | return eError;
280 | }
281 |
282 | /* OMX_GetRolesOfComponent */
283 | OMX_ERRORTYPE OMX_GetRolesOfComponent (
284 | OMX_IN OMX_STRING compName,
285 | OMX_INOUT OMX_U32 *pNumRoles,
286 | OMX_OUT OMX_U8 **roles)
287 | {
288 | OMX_ERRORTYPE eError = OMX_ErrorNone;
289 |
290 | *pNumRoles = 0;
291 | return eError;
292 | }
293 |
294 | /* OMX_GetDebugInformation */
295 | OMX_ERRORTYPE OMX_GetDebugInformation (
296 | OMX_OUT OMX_STRING debugInfo,
297 | OMX_INOUT OMX_S32 *pLen)
298 | {
299 | if(ilcs_service == NULL)
300 | return OMX_ErrorBadParameter;
301 |
302 | return vcil_out_get_debug_information(ilcs_get_common(ilcs_service), debugInfo, pLen);
303 | }
304 |
305 |
306 |
307 | /* File EOF */
308 |
309 |
--------------------------------------------------------------------------------
/libs/ilclient/libilclient.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemonkeyricky/piracast/04a0d2b6bec6c408ef41d872034333903f6fabe5/libs/ilclient/libilclient.a
--------------------------------------------------------------------------------
/libs/vgfont/Makefile:
--------------------------------------------------------------------------------
1 | OBJS=font.o vgft.o graphics.o
2 | LIB=libvgfont.a
3 |
4 | INCLUDES+=-I$(SDKSTAGE)/usr/include/freetype2 -I$(SDKSTAGE)/usr/include -I$(SDKSTAGE)/usr/include/arm-linux-gnueabi
5 | CFLAGS+=-D_HAVE_TIMER_T
6 |
7 | include ../../Makefile.include
8 |
9 |
--------------------------------------------------------------------------------
/libs/vgfont/font.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012, Broadcom Europe Ltd
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of the copyright holder nor the
13 | names of its contributors may be used to endorse or promote products
14 | derived from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | // Font handling for graphicsx
29 |
30 | /** @file font.c
31 | *
32 | * Fairly primitive font handling, just enough to emulate the old API.
33 | *
34 | * Hinting and Font Size
35 | *
36 | * The old API does not create fonts explicitly, it just renders them
37 | * as needed. That works fine for unhinted fonts, but for hinted fonts we
38 | * care about font size.
39 | *
40 | * Since we now *can* do hinted fonts, we should do. Regenerating the
41 | * fonts each time becomes quite slow, so we maintain a cache of fonts.
42 | *
43 | * For the typical applications which use graphics_x this is fine, but
44 | * won't work well if lots of fonts sizes are used.
45 | *
46 | * Unicode
47 | *
48 | * This API doesn't support unicode at all at present, nor UTF-8.
49 | */
50 |
51 | #include
52 | #include
53 | #include
54 | #include
55 |
56 | #include "graphics_x_private.h"
57 | #include "vgft.h"
58 |
59 | #define VMCS_INSTALL_PREFIX ""
60 |
61 | /** The one and only (default) font we support for now.
62 | */
63 | static struct
64 | {
65 | const char *file;
66 | void *mem;
67 | size_t len;
68 | } default_font = { "Vera.ttf" };
69 |
70 | /** An entry in our list of fonts
71 | */
72 | typedef struct gx_font_cache_entry_t
73 | {
74 | struct gx_font_cache_entry_t *next;
75 | VGFT_FONT_T font;
76 | uint32_t ptsize; /** size in points, 26.6 */
77 | } gx_font_cache_entry_t;
78 |
79 | static char fname[128];
80 | static int inited;
81 | static gx_font_cache_entry_t *fonts;
82 |
83 | static VGFT_FONT_T *find_font(const char *text, uint32_t text_size);
84 |
85 | VCOS_STATUS_T gx_priv_font_init(const char *font_dir)
86 | {
87 | VCOS_STATUS_T ret;
88 | size_t len;
89 | int rc;
90 | if (vgft_init())
91 | {
92 | ret = VCOS_ENOMEM;
93 | goto fail_init;
94 | }
95 |
96 | int fd = -1;
97 | // search for the font
98 | sprintf(fname, "%s/%s", font_dir, default_font.file);
99 | fd = open(fname, O_RDONLY);
100 |
101 | if (fd < 0)
102 | {
103 | GX_ERROR("Could not open font file '%s'", default_font.file);
104 | ret = VCOS_ENOENT;
105 | goto fail_open;
106 | }
107 |
108 | len = lseek(fd, 0, SEEK_END);
109 | lseek(fd, 0, SEEK_SET);
110 |
111 | default_font.mem = vcos_malloc(len, default_font.file);
112 | if (!default_font.mem)
113 | {
114 | GX_ERROR("No memory for font %s", fname);
115 | ret = VCOS_ENOMEM;
116 | goto fail_mem;
117 | }
118 |
119 | rc = read(fd, default_font.mem, len);
120 | if (rc != len)
121 | {
122 | GX_ERROR("Could not read font %s", fname);
123 | ret = VCOS_EINVAL;
124 | goto fail_rd;
125 | }
126 | default_font.len = len;
127 | close(fd);
128 |
129 | GX_TRACE("Opened font file '%s'", fname);
130 |
131 | inited = 1;
132 | return VCOS_SUCCESS;
133 |
134 | fail_rd:
135 | vcos_free(default_font.mem);
136 | fail_mem:
137 | if (fd >= 0) close(fd);
138 | fail_open:
139 | vgft_term();
140 | fail_init:
141 | return ret;
142 | }
143 |
144 | void gx_priv_font_term(void)
145 | {
146 | gx_font_cache_flush();
147 | vgft_term();
148 | vcos_free(default_font.mem);
149 | }
150 |
151 | /** Render text.
152 | *
153 | * FIXME: Not at all optimal - re-renders each time.
154 | * FIXME: Not UTF-8 aware
155 | * FIXME: better caching
156 | */
157 | VCOS_STATUS_T gx_priv_render_text( GX_DISPLAY_T *disp,
158 | GRAPHICS_RESOURCE_HANDLE res,
159 | int32_t x,
160 | int32_t y,
161 | uint32_t width,
162 | uint32_t height,
163 | uint32_t fg_colour,
164 | uint32_t bg_colour,
165 | const char *text,
166 | uint32_t text_length,
167 | uint32_t text_size )
168 | {
169 | VGfloat vg_colour[4];
170 | VGFT_FONT_T *font;
171 | VGPaint fg;
172 | GX_CLIENT_STATE_T save;
173 | VCOS_STATUS_T status = VCOS_SUCCESS;
174 | int clip = 1;
175 |
176 | vcos_demand(inited); // has gx_font_init() been called?
177 |
178 | gx_priv_save(&save, res);
179 |
180 | if (width == GRAPHICS_RESOURCE_WIDTH &&
181 | height == GRAPHICS_RESOURCE_HEIGHT)
182 | {
183 | clip = 0;
184 | }
185 |
186 | width = (width == GRAPHICS_RESOURCE_WIDTH) ? res->width : width;
187 | height = (height == GRAPHICS_RESOURCE_HEIGHT) ? res->height : height;
188 | font = find_font(text, text_size);
189 | if (!font)
190 | {
191 | status = VCOS_ENOMEM;
192 | goto finish;
193 | }
194 |
195 | // setup the clipping rectangle
196 | if (clip)
197 | {
198 | VGint coords[] = {x,y,width,height};
199 | vgSeti(VG_SCISSORING, VG_TRUE);
200 | vgSetiv(VG_SCISSOR_RECTS, 4, coords);
201 | }
202 |
203 | // setup the background colour if needed
204 | if (bg_colour != GRAPHICS_TRANSPARENT_COLOUR)
205 | {
206 | int err;
207 | VGfloat rendered_w, rendered_h;
208 | VGfloat vg_bg_colour[4];
209 |
210 | // setup the background colour...
211 | gx_priv_colour_to_paint(bg_colour, vg_bg_colour);
212 | vgSetfv(VG_CLEAR_COLOR, 4, vg_bg_colour);
213 |
214 | // fill in a rectangle...
215 | vgft_get_text_extents(font, text, text_length, (VGfloat)x, (VGfloat)y, &rendered_w, &rendered_h);
216 |
217 | if ( ( 0 < (VGint)rendered_w ) && ( 0 < (VGint)rendered_h ) )
218 | {
219 | vgClear(x, y, (VGint)rendered_w, (VGint)rendered_h);
220 | err = vgGetError();
221 | if (err)
222 | {
223 | GX_LOG("Error %d clearing bg text %d %d %g %g",
224 | err, x, y, rendered_w, rendered_h);
225 | vcos_assert(0);
226 | } // if
227 | } // if
228 | } // if
229 | // setup the foreground colour
230 | fg = vgCreatePaint();
231 | if (!fg)
232 | {
233 | status = VCOS_ENOMEM;
234 | goto finish;
235 | }
236 |
237 | // draw the foreground text
238 | vgSetParameteri(fg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
239 | gx_priv_colour_to_paint(fg_colour, vg_colour);
240 | vgSetParameterfv(fg, VG_PAINT_COLOR, 4, vg_colour);
241 | vgSetPaint(fg, VG_FILL_PATH);
242 |
243 | vgft_font_draw(font, (VGfloat)x, (VGfloat)y, text, text_length, VG_FILL_PATH);
244 |
245 | vgDestroyPaint(fg);
246 |
247 | vcos_assert(vgGetError() == 0);
248 | vgSeti(VG_SCISSORING, VG_FALSE);
249 |
250 | finish:
251 | gx_priv_restore(&save);
252 |
253 | return status;
254 | }
255 |
256 |
257 | /** Find a font in our cache, or create a new entry in the cache.
258 | *
259 | * Very primitive at present.
260 | */
261 | static VGFT_FONT_T *find_font(const char *text, uint32_t text_size)
262 | {
263 | int ptsize, dpi_x = 0, dpi_y = 0;
264 | VCOS_STATUS_T status;
265 | gx_font_cache_entry_t *font;
266 |
267 | ptsize = text_size << 6; // freetype takes size in points, in 26.6 format.
268 |
269 | for (font = fonts; font; font = font->next)
270 | {
271 | if (font->ptsize == ptsize)
272 | return &font->font;
273 | }
274 |
275 | font = vcos_malloc(sizeof(*font), "font");
276 | if (!font)
277 | return NULL;
278 |
279 | font->ptsize = ptsize;
280 |
281 | status = vgft_font_init(&font->font);
282 | if (status != VCOS_SUCCESS)
283 | {
284 | vcos_free(font);
285 | return NULL;
286 | }
287 |
288 | // load the font
289 | status = vgft_font_load_mem(&font->font, default_font.mem, default_font.len);
290 | if (status != VCOS_SUCCESS)
291 | {
292 | GX_LOG("Could not load font from memory: %d", status);
293 | vgft_font_term(&font->font);
294 | vcos_free(font);
295 | return NULL;
296 | }
297 |
298 | status = vgft_font_convert_glyphs(&font->font, ptsize, dpi_x, dpi_y);
299 | if (status != VCOS_SUCCESS)
300 | {
301 | GX_LOG("Could not convert font '%s' at size %d", fname, ptsize);
302 | vgft_font_term(&font->font);
303 | vcos_free(font);
304 | return NULL;
305 | }
306 |
307 | font->next = fonts;
308 | fonts = font;
309 |
310 | return &font->font;
311 | }
312 |
313 | void gx_font_cache_flush(void)
314 | {
315 | while (fonts != NULL)
316 | {
317 | struct gx_font_cache_entry_t *next = fonts->next;
318 | vgft_font_term(&fonts->font);
319 | vcos_free(fonts);
320 | fonts = next;
321 | }
322 | }
323 |
324 | int32_t graphics_resource_text_dimensions_ext(GRAPHICS_RESOURCE_HANDLE res,
325 | const char *text,
326 | const uint32_t text_length,
327 | uint32_t *width,
328 | uint32_t *height,
329 | const uint32_t text_size )
330 | {
331 | GX_CLIENT_STATE_T save;
332 | VGfloat w, h;
333 | int ret = -1;
334 |
335 | gx_priv_save(&save, res);
336 |
337 | VGFT_FONT_T *font = find_font(text, text_size);
338 | if (!font)
339 | goto finish;
340 |
341 |
342 | vgft_get_text_extents(font, text, text_length, 0.0, 0.0, &w, &h);
343 | *width = w;
344 | *height = h;
345 | ret = 0;
346 |
347 | finish:
348 | gx_priv_restore(&save);
349 | return ret;
350 | }
351 |
352 |
--------------------------------------------------------------------------------
/libs/vgfont/graphics_x_private.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012, Broadcom Europe Ltd
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of the copyright holder nor the
13 | names of its contributors may be used to endorse or promote products
14 | derived from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | // Graphics library for VG
29 |
30 | #ifndef GRAPHICS_X_PRIVATE_H
31 | #define GRAPHICS_X_PRIVATE_H
32 |
33 | #define VCOS_LOG_CATEGORY (&gx_log_cat)
34 |
35 | #include "EGL/egl.h"
36 | #include "EGL/eglext.h"
37 | #include "VG/openvg.h"
38 | #include "VG/vgu.h"
39 |
40 | #include "vgfont.h"
41 | #include "bcm_host.h"
42 |
43 | extern VCOS_LOG_CAT_T gx_log_cat;
44 |
45 | #define LOG_ERR( fmt, arg... ) vcos_log_error( "%s:%d " fmt, __func__, __LINE__, ##arg)
46 |
47 | #define GX_ERROR(format, arg...) if (1) {} else printf( format "\n", ##arg)
48 | #define GX_LOG(format, arg...) if (1) {} else printf( format "\n", ##arg)
49 | #define GX_TRACE(format, arg...) if (1) {} else printf( format "\n", ##arg)
50 |
51 | typedef struct
52 | {
53 | EGL_DISPMANX_WINDOW_T egl_win;
54 | } GX_NATIVE_WINDOW_T;
55 |
56 | typedef enum
57 | {
58 | GX_TOP_BOTTOM,
59 | GX_BOTTOM_TOP,
60 | } GX_RASTER_ORDER_T;
61 |
62 | typedef struct {} GX_PAINT_T;
63 |
64 | typedef struct GX_CLIENT_STATE_T GX_CLIENT_STATE_T;
65 | typedef struct {
66 | EGLDisplay disp;
67 | } GX_DISPLAY_T;
68 |
69 | struct GX_DISPLAY_T
70 | {
71 | EGLDisplay disp;
72 | };
73 |
74 | typedef enum
75 | {
76 | GX_WINDOW, GX_PIXMAP, GX_PBUFFER
77 | } GX_RES_TYPE;
78 |
79 | #define RES_MAGIC ('G'<<24|'X'<<16|'R'<<8|'S'<<0)
80 | #define GX_PRIV_FLAG_FLIP (1<<0)
81 |
82 | /**
83 | * Structure encapsulating the per-surface state.
84 | ***********************************************************/
85 | typedef struct GRAPHICS_RESOURCE_HANDLE_TABLE_T
86 | {
87 | union
88 | {
89 | GX_NATIVE_WINDOW_T native_window;
90 | VGImage pixmap;
91 | } u;
92 | GX_RES_TYPE type;
93 |
94 | uint32_t magic; /** To work around broken create interface */
95 | int context_bound;
96 | const char *last_caller;
97 | EGLSurface surface;
98 | EGLContext context;
99 | EGLConfig config;
100 | uint32_t screen_id; /** 0-LCD, etc */
101 | uint16_t width;
102 | uint16_t height;
103 | GRAPHICS_RESOURCE_TYPE_T restype;
104 | VC_DISPMAN_TRANSFORM_T transform;
105 |
106 | VC_RECT_T dest; /** destination rectangle in use, for book-keeping */
107 |
108 | VGfloat alpha;
109 | } GRAPHICS_RESOURCE_HANDLE_TABLE_T;
110 |
111 | /**
112 | * Structure used to store an EGL client state.
113 | ***********************************************************/
114 | struct GX_CLIENT_STATE_T
115 | {
116 | EGLSurface read_surface;
117 | EGLSurface draw_surface;
118 | EGLContext context;
119 | EGLenum api;
120 | GRAPHICS_RESOURCE_HANDLE res;
121 | };
122 |
123 | /**
124 | * \fixme add documentation
125 | *
126 | ***********************************************************/
127 | void gx_priv_init(void);
128 |
129 | /**
130 | * \fixme add documentation
131 | *
132 | ***********************************************************/
133 | void gx_priv_destroy(void);
134 |
135 | /**
136 | * \fixme add documentation
137 | *
138 | * @param col colour
139 | *
140 | * @param rgba OpenVG paint colour
141 | *
142 | ***********************************************************/
143 | void gx_priv_colour_to_paint(uint32_t col, VGfloat *rgba);
144 |
145 | /**
146 | * Save current EGL client state.
147 | *
148 | * @param state upon return, holds the saved EGL client state.
149 | *
150 | * @param res handle to the surface the EGL client state belongs to (may be NULL
).
151 | *
152 | */
153 | void gx_priv_save(GX_CLIENT_STATE_T *state, GRAPHICS_RESOURCE_HANDLE res);
154 |
155 | /**
156 | * Restore current EGL client state.
157 | *
158 | * @param state the EGL client state to restore.
159 | *
160 | */
161 | void gx_priv_restore(GX_CLIENT_STATE_T *state);
162 |
163 | /**
164 | * Create a native window for a surface.
165 | *
166 | * @param screen_id \fixme
167 | *
168 | * @param w width of the window
169 | *
170 | * @param h height of the window
171 | *
172 | * @param type color/raster format of the resource
173 | *
174 | * @param win upon successful return, holds a handle to the native window
175 | *
176 | * @param cookie \fixme
177 | *
178 | * @return VCOS_SUCCESS on success, or error code.
179 | */
180 | int gx_priv_create_native_window(uint32_t screen_id,
181 | uint32_t w, uint32_t h,
182 | GRAPHICS_RESOURCE_TYPE_T type,
183 | GX_NATIVE_WINDOW_T *win,
184 | void **cookie);
185 |
186 | /**
187 | * Destroy native window bound to surface.
188 | *
189 | * @param res Handle to surface.
190 | *
191 | */
192 | void gx_priv_destroy_native_window(GRAPHICS_RESOURCE_HANDLE_TABLE_T *res);
193 |
194 | /**
195 | * Initialise font from the given directory.
196 | *
197 | * @param font_dir path to font
198 | *
199 | * \fixme only supports Vera.tff at the moment?
200 | *
201 | * @return VCOS_SUCCESS on success, or error code.
202 | */
203 | VCOS_STATUS_T gx_priv_font_init(const char *font_dir);
204 |
205 | /**
206 | * \fixme add documentation
207 | *
208 | ***********************************************************/
209 | void gx_priv_font_term(void);
210 |
211 | /**
212 | * Fill an area of a surface with a single colour.
213 | *
214 | * @param res Handle to surface.
215 | *
216 | * @param x x-offset of area to fill
217 | *
218 | * @param y y-offset of area to fill
219 | *
220 | * @param width width of area to fill
221 | *
222 | * @param height height of area to fill
223 | *
224 | * @param fill_colour fill colour
225 | *
226 | ***********************************************************/
227 | VCOS_STATUS_T gx_priv_resource_fill(GRAPHICS_RESOURCE_HANDLE res,
228 | uint32_t x,
229 | uint32_t y,
230 | uint32_t width,
231 | uint32_t height,
232 | uint32_t fill_colour );
233 |
234 | /**
235 | * Render text into a surface
236 | *
237 | * @param disp Handle to display.
238 | *
239 | * @param res Handle to surface.
240 | *
241 | * @param x x-offset
242 | *
243 | * @param y y-offset
244 | *
245 | * @param width bounding rectangle width
246 | *
247 | * @param height bounding rectangle height
248 | *
249 | * @param fg_colour foreground color
250 | *
251 | * @param bg_colour background color
252 | *
253 | * @param text text to render
254 | *
255 | * @param text_length length of text
256 | *
257 | * @param text_size size of text
258 | *
259 | ***********************************************************/
260 | VCOS_STATUS_T gx_priv_render_text( GX_DISPLAY_T *disp,
261 | GRAPHICS_RESOURCE_HANDLE res,
262 | int32_t x,
263 | int32_t y,
264 | uint32_t width,
265 | uint32_t height,
266 | uint32_t fg_colour,
267 | uint32_t bg_colour,
268 | const char *text,
269 | uint32_t text_length,
270 | uint32_t text_size );
271 |
272 | /**
273 | * Flush a surface.
274 | *
275 | * @param res Handle to surface.
276 | *
277 | ***********************************************************/
278 | void gx_priv_flush(GRAPHICS_RESOURCE_HANDLE res);
279 |
280 | /**
281 | * Called after the EGL/VG initialisation of a window has completed
282 | * following its creation.
283 | *
284 | * @param res ???
285 | *
286 | * @param cookie ???
287 | *
288 | ***********************************************************/
289 | void gx_priv_finish_native_window(GRAPHICS_RESOURCE_HANDLE_TABLE_T *res,
290 | void *cookie);
291 |
292 | /**
293 | * Flush font cache.
294 | *
295 | ***********************************************************/
296 | void gx_font_cache_flush(void);
297 |
298 | /**
299 | * Read a bitmap (.BMP) image from the given file.
300 | *
301 | * @param filename filename (must not be NULL
).
302 | *
303 | * @param width holds the width of the image upon return.
304 | *
305 | * @param height holds the height of the image upon return.
306 | *
307 | * @param pitch_bytes holds the pitch of the image data (in bytes) upon return.
308 | *
309 | * @param restype holds the type of the image upon return.
310 | *
311 | * @param vg_format holds the OpenVG image format upon return.
312 | *
313 | * @param flags holds flags describing image properties upon return.
314 | *
315 | * @param image_data_size holds size of the image data upon return.
316 | *
317 | * @param pimage_data holds the image data buffer upon return (must not be NULL
),
318 | * the caller is responsible for releasing the buffer afterwards.
319 | *
320 | * @return 0 if success, non-zero otherwise (in which case the output parameters
321 | * may be invalid).
322 | *
323 | ***********************************************************/
324 | int gx_priv_read_bmp(const char *file_name,
325 | uint32_t *width, uint32_t *height, uint32_t *pitch_bytes,
326 | GRAPHICS_RESOURCE_TYPE_T *restype,
327 | VGImageFormat *vg_format,
328 | uint32_t *flags,
329 | uint32_t *image_data_size,
330 | void **pimage_data);
331 |
332 | /**
333 | * Read a Targa (.TGA) image from the given file.
334 | *
335 | * @param filename filename (must not be NULL
).
336 | *
337 | * @param width holds the width of the image upon return.
338 | *
339 | * @param height holds the height of the image upon return.
340 | *
341 | * @param pitch_bytes holds the pitch of the image data (in bytes) upon return.
342 | *
343 | * @param restype holds the type of the image upon return.
344 | *
345 | * @param vg_format holds the OpenVG image format upon return.
346 | *
347 | * @param flags holds flags describing image properties upon return.
348 | *
349 | * @param image_data_size holds size of the image data upon return.
350 | *
351 | * @param pimage_data holds the image data buffer upon return (must not be NULL
),
352 | * the caller is responsible for releasing the memory afterwards.
353 | *
354 | * @return 0 if success, non-zero otherwise (in which case the output parameters.
355 | * may be invalid).
356 | *
357 | ***********************************************************/
358 | int gx_priv_read_tga(const char *file_name,
359 | uint32_t *width, uint32_t *height, uint32_t *pitch_bytes,
360 | GRAPHICS_RESOURCE_TYPE_T *restype,
361 | VGImageFormat *vg_format,
362 | uint32_t *flags,
363 | uint32_t *image_data_size,
364 | void **pimage_data);
365 |
366 | #endif
367 |
--------------------------------------------------------------------------------
/libs/vgfont/libvgfont.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemonkeyricky/piracast/04a0d2b6bec6c408ef41d872034333903f6fabe5/libs/vgfont/libvgfont.a
--------------------------------------------------------------------------------
/libs/vgfont/vgfont.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012, Broadcom Europe Ltd
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of the copyright holder nor the
13 | names of its contributors may be used to endorse or promote products
14 | derived from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | // Font handling for graphicsx
29 |
30 | #ifndef VCFTLIB_H
31 | #define VCFTLIB_H
32 |
33 | #include
34 | #include "interface/vmcs_host/vc_dispservice_x_defs.h"
35 | #include "interface/vctypes/vc_image_types.h"
36 | #include "interface/vcos/vcos.h"
37 |
38 | //Definitions which in certain functions can be used to mean the actual width and height of a resource, without
39 | //having to know the data implicitly.
40 | #define GRAPHICS_RESOURCE_WIDTH 0xFFFF
41 | #define GRAPHICS_RESOURCE_HEIGHT 0xFFFF
42 |
43 | #define R_888_MASK (0x00FF0000)
44 | #define G_888_MASK (0x0000FF00)
45 | #define B_888_MASK (0x000000FF)
46 | #define ALPHA_888_MASK (0xFF000000)
47 | #define GRAPHICS_RGBA32( r, g, b, a ) GRAPHICS_RGBA888( r, g, b, a )
48 | #define GRAPHICS_RGBA888( r, g, b, a ) ( (((a) << (8+8+8)) & ALPHA_888_MASK) | (((b) << (8+8)) & R_888_MASK) | (((g) << 8) & G_888_MASK) | ((r) & B_888_MASK) )
49 | #define GRAPHICS_TRANSPARENT_COLOUR 0x00000001UL
50 |
51 | //resource defs
52 |
53 | typedef enum
54 | {
55 | GRAPHICS_RESOURCE_HANDLE_TYPE_MIN,
56 |
57 | GRAPHICS_RESOURCE_RGB565,
58 | GRAPHICS_RESOURCE_RGB888, /* 888 format is ONLY used when loading bitmaps
59 | - you can't create or delete bitmaps with this format */
60 | GRAPHICS_RESOURCE_RGBA32,
61 | GRAPHICS_RESOURCE_TF_RGB32A,
62 | GRAPHICS_RESOURCE_TF_RGB565,
63 | GRAPHICS_RESOURCE_YUV420,
64 |
65 | GRAPHICS_RESOURCE_HANDLE_TYPE_MAX
66 |
67 | } GRAPHICS_RESOURCE_TYPE_T;
68 |
69 |
70 | typedef struct GRAPHICS_RESOURCE_HANDLE_TABLE_T *GRAPHICS_RESOURCE_HANDLE;
71 |
72 | VCOS_STATUS_T gx_graphics_init(const char *font_dir);
73 | int32_t graphics_delete_resource( GRAPHICS_RESOURCE_HANDLE res );
74 | VCOS_STATUS_T gx_create_window( uint32_t screen_id,
75 | uint32_t width,
76 | uint32_t height,
77 | GRAPHICS_RESOURCE_TYPE_T image_type,
78 | GRAPHICS_RESOURCE_HANDLE *resource_handle );
79 |
80 | int32_t graphics_display_resource( GRAPHICS_RESOURCE_HANDLE res,
81 | const uint16_t screen_number,
82 | const int16_t z_order,
83 | const uint16_t offset_x,
84 | const uint16_t offset_y,
85 | const uint16_t dest_width,
86 | const uint16_t dest_height,
87 | const VC_DISPMAN_TRANSFORM_T transform,
88 | const uint8_t display );
89 |
90 | int32_t graphics_resource_fill(GRAPHICS_RESOURCE_HANDLE res,
91 | uint32_t x,
92 | uint32_t y,
93 | uint32_t width,
94 | uint32_t height,
95 | uint32_t fill_colour );
96 |
97 | int32_t graphics_update_displayed_resource(GRAPHICS_RESOURCE_HANDLE res,
98 | const uint32_t x_offset,
99 | const uint32_t y_offset,
100 | const uint32_t width,
101 | const uint32_t height );
102 |
103 | int32_t graphics_resource_render_text_ext( GRAPHICS_RESOURCE_HANDLE res,
104 | const int32_t x,
105 | const int32_t y,
106 | const uint32_t width,
107 | const uint32_t height,
108 | const uint32_t fg_colour,
109 | const uint32_t bg_colour,
110 | const char *text,
111 | const uint32_t text_length,
112 | const uint32_t text_size );
113 |
114 | int32_t graphics_resource_text_dimensions_ext(GRAPHICS_RESOURCE_HANDLE res,
115 | const char *text,
116 | const uint32_t text_length,
117 | uint32_t *width,
118 | uint32_t *height,
119 | const uint32_t text_size );
120 |
121 | int32_t graphics_get_resource_size(
122 | const GRAPHICS_RESOURCE_HANDLE res,
123 | uint32_t *w,
124 | uint32_t *h);
125 |
126 | int32_t graphics_update_start(void);
127 |
128 | int32_t graphics_update_end( void );
129 |
130 | int32_t graphics_resource_text_dimensions( GRAPHICS_RESOURCE_HANDLE resource_handle,
131 | const char *text,
132 | const uint32_t text_length,
133 | uint32_t *width,
134 | uint32_t *height );
135 |
136 | #endif
137 |
--------------------------------------------------------------------------------
/libs/vgfont/vgft.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012, Broadcom Europe Ltd
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of the copyright holder nor the
13 | names of its contributors may be used to endorse or promote products
14 | derived from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | // Font handling for graphicsx
29 |
30 | #include
31 | #include
32 |
33 | #include "graphics_x_private.h"
34 | #include "vgft.h"
35 |
36 | static FT_Library lib;
37 |
38 | int vgft_init(void)
39 | {
40 | if (FT_Init_FreeType(&lib) == 0)
41 | return 0;
42 | else
43 | {
44 | return -1;
45 | }
46 | }
47 |
48 | void vgft_term(void)
49 | {
50 | FT_Done_FreeType(lib);
51 | }
52 |
53 | #define SEGMENTS_COUNT_MAX 256
54 | #define COORDS_COUNT_MAX 1024
55 |
56 | static VGuint segments_count;
57 | static VGubyte segments[SEGMENTS_COUNT_MAX];
58 | static VGuint coords_count;
59 | static VGfloat coords[COORDS_COUNT_MAX];
60 |
61 | static VGfloat float_from_26_6(FT_Pos x)
62 | {
63 | return (VGfloat)x / 64.0f;
64 | }
65 |
66 | static void convert_contour(const FT_Vector *points, const char *tags, short points_count)
67 | {
68 | int first_coords = coords_count;
69 |
70 | int first = 1;
71 | char last_tag = 0;
72 | int c = 0;
73 |
74 | for (; points_count != 0; ++points, ++tags, --points_count) {
75 | ++c;
76 |
77 | char tag = *tags;
78 | if (first) {
79 | assert(tag & 0x1);
80 | assert(c==1); c=0;
81 | segments[segments_count++] = VG_MOVE_TO;
82 | first = 0;
83 | } else if (tag & 0x1) {
84 | /* on curve */
85 |
86 | if (last_tag & 0x1) {
87 | /* last point was also on -- line */
88 | assert(c==1); c=0;
89 | segments[segments_count++] = VG_LINE_TO;
90 | } else {
91 | /* last point was off -- quad or cubic */
92 | if (last_tag & 0x2) {
93 | /* cubic */
94 | assert(c==3); c=0;
95 | segments[segments_count++] = VG_CUBIC_TO;
96 | } else {
97 | /* quad */
98 | assert(c==2); c=0;
99 | segments[segments_count++] = VG_QUAD_TO;
100 | }
101 | }
102 | } else {
103 | /* off curve */
104 |
105 | if (tag & 0x2) {
106 | /* cubic */
107 |
108 | assert((last_tag & 0x1) || (last_tag & 0x2)); /* last either on or off and cubic */
109 | } else {
110 | /* quad */
111 |
112 | if (!(last_tag & 0x1)) {
113 | /* last was also off curve */
114 |
115 | assert(!(last_tag & 0x2)); /* must be quad */
116 |
117 | /* add on point half-way between */
118 | assert(c==2); c=1;
119 | segments[segments_count++] = VG_QUAD_TO;
120 | VGfloat x = (coords[coords_count - 2] + float_from_26_6(points->x)) * 0.5f;
121 | VGfloat y = (coords[coords_count - 1] + float_from_26_6(points->y)) * 0.5f;
122 | coords[coords_count++] = x;
123 | coords[coords_count++] = y;
124 | }
125 | }
126 | }
127 | last_tag = tag;
128 |
129 | coords[coords_count++] = float_from_26_6(points->x);
130 | coords[coords_count++] = float_from_26_6(points->y);
131 | }
132 |
133 | if (last_tag & 0x1) {
134 | /* last point was also on -- line (implicit with close path) */
135 | assert(c==0);
136 | } else {
137 | ++c;
138 |
139 | /* last point was off -- quad or cubic */
140 | if (last_tag & 0x2) {
141 | /* cubic */
142 | assert(c==3); c=0;
143 | segments[segments_count++] = VG_CUBIC_TO;
144 | } else {
145 | /* quad */
146 | assert(c==2); c=0;
147 | segments[segments_count++] = VG_QUAD_TO;
148 | }
149 |
150 | coords[coords_count++] = coords[first_coords + 0];
151 | coords[coords_count++] = coords[first_coords + 1];
152 | }
153 |
154 | segments[segments_count++] = VG_CLOSE_PATH;
155 | }
156 |
157 | static void convert_outline(const FT_Vector *points, const char *tags, const short *contours, short contours_count, short points_count)
158 | {
159 | segments_count = 0;
160 | coords_count = 0;
161 |
162 | short last_contour = 0;
163 | for (; contours_count != 0; ++contours, --contours_count) {
164 | short contour = *contours + 1;
165 | convert_contour(points + last_contour, tags + last_contour, contour - last_contour);
166 | last_contour = contour;
167 | }
168 | assert(last_contour == points_count);
169 |
170 | assert(segments_count <= SEGMENTS_COUNT_MAX); /* oops... we overwrote some memory */
171 | assert(coords_count <= COORDS_COUNT_MAX);
172 | }
173 |
174 | VCOS_STATUS_T vgft_font_init(VGFT_FONT_T *font)
175 | {
176 | font->ft_face = NULL;
177 | font->vg_font = vgCreateFont(0);
178 | if (font->vg_font == VG_INVALID_HANDLE)
179 | {
180 | return VCOS_ENOMEM;
181 | }
182 | return VCOS_SUCCESS;
183 | }
184 |
185 | VCOS_STATUS_T vgft_font_load_mem(VGFT_FONT_T *font, void *mem, size_t len)
186 | {
187 | if (FT_New_Memory_Face(lib, mem, len, 0, &font->ft_face))
188 | {
189 | return VCOS_EINVAL;
190 | }
191 | return VCOS_SUCCESS;
192 | }
193 |
194 | VCOS_STATUS_T vgft_font_load_file(VGFT_FONT_T *font, const char *file)
195 | {
196 | if (FT_New_Face(lib, file, 0, &font->ft_face)) {
197 | return VCOS_EINVAL;
198 | }
199 | return VCOS_SUCCESS;
200 | }
201 |
202 | VCOS_STATUS_T vgft_font_convert_glyphs(VGFT_FONT_T *font, unsigned int char_height, unsigned int dpi_x, unsigned int dpi_y)
203 | {
204 | FT_UInt glyph_index;
205 | FT_ULong ch;
206 |
207 | if (FT_Set_Char_Size(font->ft_face, 0, char_height, dpi_x, dpi_y))
208 | {
209 | FT_Done_Face(font->ft_face);
210 | vgDestroyFont(font->vg_font);
211 | return VCOS_EINVAL;
212 | }
213 |
214 | ch = FT_Get_First_Char(font->ft_face, &glyph_index);
215 |
216 | while (ch != 0)
217 | {
218 | if (FT_Load_Glyph(font->ft_face, glyph_index, FT_LOAD_DEFAULT)) {
219 | FT_Done_Face(font->ft_face);
220 | vgDestroyFont(font->vg_font);
221 | return VCOS_ENOMEM;
222 | }
223 |
224 | VGPath vg_path;
225 | FT_Outline *outline = &font->ft_face->glyph->outline;
226 | if (outline->n_contours != 0) {
227 | vg_path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
228 | assert(vg_path != VG_INVALID_HANDLE);
229 |
230 | convert_outline(outline->points, outline->tags, outline->contours, outline->n_contours, outline->n_points);
231 | vgAppendPathData(vg_path, segments_count, segments, coords);
232 | } else {
233 | vg_path = VG_INVALID_HANDLE;
234 | }
235 |
236 | VGfloat origin[] = { 0.0f, 0.0f };
237 | VGfloat escapement[] = { float_from_26_6(font->ft_face->glyph->advance.x), float_from_26_6(font->ft_face->glyph->advance.y) };
238 | vgSetGlyphToPath(font->vg_font, glyph_index, vg_path, VG_FALSE, origin, escapement);
239 |
240 | if (vg_path != VG_INVALID_HANDLE) {
241 | vgDestroyPath(vg_path);
242 | }
243 | ch = FT_Get_Next_Char(font->ft_face, ch, &glyph_index);
244 | }
245 |
246 | return VCOS_SUCCESS;
247 | }
248 |
249 | void vgft_font_term(VGFT_FONT_T *font)
250 | {
251 | if (font->ft_face)
252 | FT_Done_Face(font->ft_face);
253 | if (font->vg_font)
254 | vgDestroyFont(font->vg_font);
255 | memset(font, 0, sizeof(*font));
256 | }
257 |
258 | #define GLYPHS_COUNT_MAX 200
259 |
260 | static VGuint glyph_indices[GLYPHS_COUNT_MAX];
261 | static VGfloat adjustments_x[GLYPHS_COUNT_MAX];
262 | static VGfloat adjustments_y[GLYPHS_COUNT_MAX];
263 |
264 | static void draw_line(VGFT_FONT_T *font, VGfloat x, VGfloat y, const char *text, int glyphs_count, VGbitfield paint_modes)
265 | {
266 | if (glyphs_count == 0) return;
267 |
268 | assert(glyphs_count <= GLYPHS_COUNT_MAX);
269 |
270 | VGfloat glor[] = { x, y };
271 | vgSetfv(VG_GLYPH_ORIGIN, 2, glor);
272 |
273 | int i;
274 | int prev_glyph_index = 0;
275 | for (i = 0; i != glyphs_count; ++i) {
276 |
277 | int glyph_index = FT_Get_Char_Index(font->ft_face, text[i]);
278 | if (!glyph_index) { return; }
279 |
280 | glyph_indices[i] = glyph_index;
281 |
282 | if (i != 0) {
283 | FT_Vector kern;
284 | if (FT_Get_Kerning(font->ft_face, prev_glyph_index, glyph_index, FT_KERNING_DEFAULT, &kern)) {
285 | assert(0);
286 | }
287 |
288 | adjustments_x[i - 1] = float_from_26_6(kern.x);
289 | adjustments_y[i - 1] = float_from_26_6(kern.y);
290 | }
291 |
292 | prev_glyph_index = glyph_index;
293 | }
294 |
295 | adjustments_x[glyphs_count - 1] = 0.0f;
296 | adjustments_y[glyphs_count - 1] = 0.0f;
297 |
298 | vgDrawGlyphs(font->vg_font, glyphs_count, glyph_indices, adjustments_x, adjustments_y, paint_modes, VG_FALSE);
299 | }
300 |
301 | void vgft_font_draw(VGFT_FONT_T *font, VGfloat x, VGfloat y, const char *text, unsigned text_length, VGbitfield paint_modes)
302 | {
303 | VGfloat descent = float_from_26_6(font->ft_face->size->metrics.descender);
304 | int last_draw = 0;
305 | int i = 0;
306 | y -= descent;
307 | for (;;) {
308 | int last = !text[i] || (text_length && i==text_length);
309 |
310 | if ((text[i] == '\n') || last)
311 | {
312 | draw_line(font, x, y, text + last_draw, i - last_draw, paint_modes);
313 | last_draw = i+1;
314 | y -= float_from_26_6(font->ft_face->size->metrics.height);
315 | }
316 | if (last)
317 | {
318 | break;
319 | }
320 | ++i;
321 | }
322 | }
323 |
324 | // Get text extents for a single line
325 |
326 | static void line_extents(VGFT_FONT_T *font, VGfloat *x, VGfloat *y, const char *text, int chars_count)
327 | {
328 | int i;
329 | int prev_glyph_index = 0;
330 | if (chars_count == 0) return;
331 |
332 | for (i=0; i < chars_count; i++)
333 | {
334 | int glyph_index = FT_Get_Char_Index(font->ft_face, text[i]);
335 | if (!glyph_index) return;
336 |
337 | if (i != 0)
338 | {
339 | FT_Vector kern;
340 | if (FT_Get_Kerning(font->ft_face, prev_glyph_index, glyph_index,
341 | FT_KERNING_DEFAULT, &kern))
342 | {
343 | assert(0);
344 | }
345 | *x += float_from_26_6(kern.x);
346 | *y += float_from_26_6(kern.y);
347 | }
348 | FT_Load_Glyph(font->ft_face, glyph_index, FT_LOAD_DEFAULT);
349 | *x += float_from_26_6(font->ft_face->glyph->advance.x);
350 | }
351 | }
352 |
353 | // Text extents for some ASCII text.
354 | //
355 | // Use text_length if non-zero, otherwise look for trailing '\0'.
356 |
357 | void vgft_get_text_extents(VGFT_FONT_T *font,
358 | const char *text,
359 | unsigned text_length,
360 | VGfloat start_x, VGfloat start_y,
361 | VGfloat *w, VGfloat *h) {
362 | int last_draw = 0;
363 | VGfloat max_x = start_x;
364 | VGfloat y = start_y;
365 |
366 | int i, last;
367 | for (i = 0, last = 0; !last; ++i) {
368 | last = !text[i] || (text_length && i==text_length);
369 | if ((text[i] == '\n') || last) {
370 | VGfloat x = 0;
371 | line_extents(font, &x, &y, text + last_draw, i - last_draw);
372 | last_draw = i+1;
373 | y -= float_from_26_6(font->ft_face->size->metrics.height);
374 | if (x > max_x) max_x = x;
375 | }
376 | }
377 | *w = max_x - start_x;
378 | *h = start_y - y;
379 | }
380 |
--------------------------------------------------------------------------------
/libs/vgfont/vgft.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012, Broadcom Europe Ltd
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | * Neither the name of the copyright holder nor the
13 | names of its contributors may be used to endorse or promote products
14 | derived from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | // Font handling for graphicsx
29 |
30 | #ifndef VGFT_H
31 | #define VGFT_H
32 |
33 | #include "interface/vcos/vcos.h"
34 | #include
35 | #include
36 |
37 | typedef int VGFT_BOOL;
38 | #define VGFT_FALSE 0
39 | #define VGFT_TRUE (!VGFT_FALSE)
40 |
41 | #include FT_FREETYPE_H
42 |
43 | /* Returns 0 on success */
44 | extern int vgft_init(void);
45 | extern void vgft_term(void);
46 |
47 | typedef struct {
48 | VGFont vg_font;
49 | FT_Face ft_face;
50 | } VGFT_FONT_T;
51 |
52 | /** Initialise a FT->VG font */
53 | VCOS_STATUS_T vgft_font_init(VGFT_FONT_T *font);
54 |
55 | /** Load a font file from memory */
56 | VCOS_STATUS_T vgft_font_load_mem(VGFT_FONT_T *font, void *mem, size_t len);
57 |
58 | /** Convert a font into VG glyphs */
59 | VCOS_STATUS_T vgft_font_convert_glyphs(VGFT_FONT_T *font, unsigned int char_height, unsigned int dpi_x, unsigned int dpi_y);
60 |
61 | /** Release a font. */
62 | void vgft_font_term(VGFT_FONT_T *font);
63 |
64 | void vgft_font_draw(VGFT_FONT_T *font, VGfloat x, VGfloat y, const char *text, unsigned text_length, VGbitfield paint_modes);
65 |
66 | void vgft_get_text_extents(VGFT_FONT_T *font, const char *text, unsigned text_length, VGfloat x, VGfloat y,
67 | VGfloat *w, VGfloat *h);
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/mgmt_audio_decoder/inc/sx_mgmt_audio_decoder.h:
--------------------------------------------------------------------------------
1 | #if !defined(SX_MGMT_AUDIO_DECODER_H)
2 | #define SX_MGMT_AUDIO_DECODER_H
3 |
4 | extern void sx_mgmt_audio_decoder_init(
5 | void
6 | );
7 |
8 | extern void sx_mgmt_audio_decoder_open(
9 | void
10 | );
11 |
12 | extern void sx_mgmt_audio_decoder_close(
13 | void
14 | );
15 |
16 | #endif
17 |
18 |
--------------------------------------------------------------------------------
/mgmt_audio_decoder/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_audio_decoder/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common desc pipe video_decoder_hw audio_sink
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_audio_decoder/src/sx_mgmt_audio_decoder.c:
--------------------------------------------------------------------------------
1 | // ========================================================
2 | // Includes
3 | // ========================================================
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #include "sx_pkt.h"
15 | #include "sx_desc.h"
16 | #include "sx_pipe.h"
17 | #include "sx_thread_priority.h"
18 | #include "sx_audio_sink.h"
19 |
20 | // ========================================================
21 | // Constants
22 | // ========================================================
23 |
24 | // ========================================================
25 | // Private Types
26 | // ========================================================
27 |
28 | typedef struct
29 | {
30 | sSX_DESC *head;
31 | sSX_DESC *tail;
32 |
33 | } sSLICE_CHAIN;
34 |
35 | // Decoder control block
36 | typedef struct
37 | {
38 | pthread_t decoder_thread;
39 | UINT32 look_for_new_slice;
40 | UINT32 continue_current_slice;
41 | UINT32 pes_len;
42 | UINT32 pes_curr_byte_count;
43 | UINT32 last_seq_num;
44 | sSLICE_CHAIN slice_chain;
45 |
46 | } sDECODER_CBLK;
47 |
48 |
49 | // ========================================================
50 | // Private Variables & Functions
51 | // ========================================================
52 |
53 | // Decoder control block.
54 | static sDECODER_CBLK f_cblk;
55 |
56 | static sSX_DESC * slice_get(
57 | void
58 | )
59 | {
60 | sSX_DESC *head;
61 |
62 |
63 | head = f_cblk.slice_chain.head;
64 |
65 | f_cblk.slice_chain.head = NULL;
66 | f_cblk.slice_chain.tail = NULL;
67 |
68 | // printf("slice_get() invoked\n");
69 |
70 | return head;
71 | }
72 |
73 |
74 | static void slice_drop(
75 | void
76 | )
77 | {
78 | sSX_DESC *curr;
79 | sSX_DESC *next;
80 |
81 |
82 | // Drop slice.
83 | sx_desc_put(f_cblk.slice_chain.head);
84 |
85 | // Reset head and tail.
86 | f_cblk.slice_chain.head = NULL;
87 | f_cblk.slice_chain.tail = NULL;
88 |
89 | printf("slice_dropped() invoked\n");
90 | }
91 |
92 |
93 | static void audio_decoder_slice_dump(
94 | sSX_DESC *slice_head
95 | )
96 | {
97 | sx_pipe_put(SX_VRDMA_LPCM_SLICE, slice_head);
98 | }
99 |
100 |
101 | static UINT32 pes_payload_size(
102 | sSX_DESC *desc
103 | )
104 | {
105 | UINT8 *curr_ptr;
106 | UINT32 bytes_left;
107 | UINT32 afc;
108 | UINT32 pid;
109 | UINT32 pes_byte_count;
110 | UINT32 payload_size;
111 |
112 |
113 | // Get current.
114 | curr_ptr = desc->data;
115 |
116 | // Get data left.
117 | bytes_left = desc->data_len;
118 | assert(bytes_left > sizeof(sRTP_HDR));
119 |
120 | // Get RTP header.
121 | // sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr;
122 |
123 | // Get TS header.
124 | curr_ptr += sizeof(sRTP_HDR);
125 |
126 | // Get TS bytes left.
127 | bytes_left -= sizeof(sRTP_HDR);
128 | assert((bytes_left % sizeof(sMPEG2_TS)) == 0);
129 |
130 | pes_byte_count = 0;
131 | do
132 | {
133 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
134 |
135 | afc = AFC_GET(ts->hdr);
136 | pid = PID_GET(ts->hdr);
137 |
138 | if(pid == 0x1100)
139 | {
140 | if(PUSI_GET(ts->hdr))
141 | {
142 | // This makes Piracast to work with Sony Xperia
143 | // As it sends afc with payload (11b)
144 | assert((afc == 0x01) || (afc == 0x03));
145 |
146 | // printf("### 0x%x 0x%x 0x%x 0x%x\n",
147 | // ts->payload.payload[14],
148 | // ts->payload.payload[15],
149 | // ts->payload.payload[16],
150 | // ts->payload.payload[17]);
151 |
152 | payload_size = (sizeof(sMPEG2_TS_PAYLOAD) - 20);
153 | }
154 | else
155 | {
156 | if(afc == 0x01)
157 | {
158 | // printf("### 2\n");
159 | payload_size = sizeof(sMPEG2_TS_PAYLOAD);
160 | }
161 | else if(afc == 0x03)
162 | {
163 | // printf("### 3\n");
164 | payload_size = sizeof(sMPEG2_TS_PAYLOAD) - 1 - ts->payload.payload[0];
165 | }
166 | else
167 | {
168 | assert(0);
169 | }
170 | }
171 |
172 | pes_byte_count += payload_size;
173 |
174 | // printf("(pes_payload_size): payload_size = %d\n", payload_size);
175 | }
176 |
177 | curr_ptr += sizeof(sMPEG2_TS);
178 | bytes_left -= sizeof(sMPEG2_TS);
179 |
180 | } while (bytes_left > 0);
181 |
182 | return pes_byte_count;
183 | }
184 |
185 |
186 | static void slice_pkt_add(
187 | sSX_DESC *desc
188 | )
189 | {
190 | assert(desc != NULL);
191 |
192 |
193 | if(f_cblk.slice_chain.head == NULL)
194 | {
195 | f_cblk.slice_chain.head = desc;
196 | f_cblk.slice_chain.tail = desc;
197 |
198 | return;
199 | }
200 |
201 | // Append to tail.
202 | f_cblk.slice_chain.tail->next = desc;
203 |
204 | // Update tail.
205 | f_cblk.slice_chain.tail = desc;
206 |
207 | // printf("slice_pkt_add() invoked\n");
208 | }
209 |
210 |
211 | static UINT8 slice_start_find(
212 | sSX_DESC *desc,
213 | UINT32 *pes_payload_size
214 | )
215 | {
216 | UINT8 *curr_ptr;
217 | UINT32 bytes_left;
218 | sMPEG2_TS *ts;
219 | UINT32 pid;
220 | UINT32 afc;
221 |
222 |
223 | // Get current.
224 | curr_ptr = desc->data;
225 |
226 | // Get data left.
227 | bytes_left = desc->data_len;
228 | assert(bytes_left > sizeof(sRTP_HDR));
229 |
230 | // Get RTP header.
231 | sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr;
232 |
233 | // Get TS header.
234 | curr_ptr += sizeof(sRTP_HDR);
235 |
236 | // Get TS bytes left.
237 | bytes_left -= sizeof(sRTP_HDR);
238 | assert((bytes_left % sizeof(sMPEG2_TS)) == 0);
239 |
240 | do
241 | {
242 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
243 |
244 | afc = AFC_GET(ts->hdr);
245 | pid = PID_GET(ts->hdr);
246 |
247 | if(PUSI_GET(ts->hdr) && (pid == 0x1100))
248 | {
249 | curr_ptr = &ts->payload.payload[0];
250 |
251 | curr_ptr += sizeof(sPES);
252 |
253 | sPES_EXT *pes_ext = (sPES_EXT *) curr_ptr;
254 |
255 | *pes_payload_size = ntohs(pes_ext->length) - 14;
256 |
257 | // PES packet length is zero for Sony Xperia
258 | assert((*pes_payload_size == 1920) || (*pes_payload_size == -14));
259 |
260 | return 1;
261 | }
262 |
263 | curr_ptr += sizeof(sMPEG2_TS);
264 | bytes_left -= sizeof(sMPEG2_TS);
265 |
266 | } while (bytes_left > 0);
267 |
268 | return 0;
269 | }
270 |
271 |
272 | // --------------------------------------------------------
273 | // decoder_thread
274 | // Decoder thread
275 | //
276 | // Description:
277 | // This function defines the decoder thread.
278 | //
279 | void audio_decoder_thread(
280 | void * arg
281 | )
282 | {
283 | sSX_DESC *desc;
284 | UINT8 *curr_ptr;
285 | UINT32 bytes_left;
286 | sMPEG2_TS *ts;
287 |
288 | // UINT32 last_seq_num = 0;
289 | UINT8 eos;
290 |
291 |
292 | while(1)
293 | {
294 | do
295 | {
296 | desc = sx_pipe_get(SX_VRDMA_LPCM);
297 | if(desc == NULL)
298 | {
299 | break;
300 | }
301 |
302 | // Get current.
303 | curr_ptr = desc->data;
304 |
305 | // Get data left.
306 | bytes_left = desc->data_len;
307 | assert(bytes_left > sizeof(sRTP_HDR));
308 |
309 | // Get RTP header.
310 | sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr;
311 |
312 | if(f_cblk.look_for_new_slice)
313 | {
314 | if(slice_start_find(desc, &f_cblk.pes_len))
315 | {
316 | f_cblk.look_for_new_slice = 0;
317 |
318 | f_cblk.continue_current_slice = 1;
319 |
320 | f_cblk.pes_curr_byte_count = 0;
321 |
322 | f_cblk.last_seq_num = ntohs(rtp_hdr->sequence_num) - 1;
323 | }
324 | }
325 |
326 | if(f_cblk.continue_current_slice)
327 | {
328 | if(ntohs(rtp_hdr->sequence_num) != (f_cblk.last_seq_num + 1))
329 | {
330 | // printf("(audio_decoder): rtp seq num = %d, last_seq_num = %d\n",
331 | // ntohs(rtp_hdr->sequence_num),
332 | // f_cblk.last_seq_num);
333 |
334 | slice_drop();
335 |
336 | f_cblk.continue_current_slice = 0;
337 | f_cblk.look_for_new_slice = 1;
338 | }
339 | else
340 | {
341 | f_cblk.last_seq_num = ntohs(rtp_hdr->sequence_num);
342 |
343 | UINT32 pes_size = pes_payload_size(desc);
344 |
345 | // assert(pes_size == 1920);
346 |
347 | // printf("(audio_decoder): PES payload size = %d\n", pes_size);
348 |
349 | f_cblk.pes_curr_byte_count += pes_size;
350 |
351 | assert(f_cblk.pes_curr_byte_count <= f_cblk.pes_len);
352 |
353 | // assert(0);
354 |
355 | slice_pkt_add(desc);
356 |
357 | if(f_cblk.pes_curr_byte_count == f_cblk.pes_len)
358 | {
359 | f_cblk.continue_current_slice = 0;
360 | f_cblk.look_for_new_slice = 1;
361 |
362 | // printf("(audio_decoder): Slice end found!\n");
363 |
364 | audio_decoder_slice_dump(slice_get());
365 | }
366 | }
367 | }
368 |
369 | } while (1);
370 |
371 |
372 | // printf("(audio_decoder): sleep!\n");
373 |
374 | usleep(1000);
375 | }
376 | }
377 |
378 |
379 | // --------------------------------------------------------
380 | // common_resource_init
381 | // Initialize common resources
382 | //
383 | // Description:
384 | // This function initializes the common resources.
385 | //
386 | static void resources_init(
387 | void
388 | )
389 | {
390 | f_cblk.look_for_new_slice = 1;
391 |
392 | // Initialize decoder hardware.
393 | sx_audio_sink_init();
394 | }
395 |
396 |
397 | // --------------------------------------------------------
398 | // decoder_thread_create
399 | // Creates decoder thread
400 | //
401 | // Description:
402 | // This function creates decoder thread.
403 | //
404 | static void decoder_thread_create(
405 | void
406 | )
407 | {
408 | sx_thread_create(&f_cblk.decoder_thread, &audio_decoder_thread, NULL, MGMT_AUDIO_DECODER_THREAD_PRIORITY);
409 | }
410 |
411 |
412 | // ========================================================
413 | // Public Functions
414 | // ========================================================
415 |
416 | // --------------------------------------------------------
417 | // sx_mgmt_audio_decoder_init
418 | // Initializes decoder
419 | //
420 | void sx_mgmt_audio_decoder_init(
421 | void
422 | )
423 | {
424 | // Initialize common resources.
425 | resources_init();
426 | }
427 |
428 |
429 | // --------------------------------------------------------
430 | // sx_mgmt_audio_decoder_open
431 | // Opens decoder
432 | //
433 | void sx_mgmt_audio_decoder_open(
434 | void
435 | )
436 | {
437 | // Initialize decoder thread.
438 | decoder_thread_create();
439 | }
440 |
441 |
442 | // --------------------------------------------------------
443 | // sx_mgmt_audio_decoder_close
444 | // Closes decoder
445 | //
446 | void sx_mgmt_audio_decoder_close(
447 | void
448 | )
449 | {
450 | }
451 |
--------------------------------------------------------------------------------
/mgmt_audio_scheduler/inc/sx_mgmt_audio_scheduler.h:
--------------------------------------------------------------------------------
1 | #if !defined(SX_MGMT_AUDIO_SCHEDULER_H)
2 | #define SX_MGMT_AUDIO_SCHEDULER_H
3 |
4 | extern void sx_mgmt_audio_scheduler_init(
5 | void
6 | );
7 |
8 | extern void sx_mgmt_audio_scheduler_open(
9 | void
10 | );
11 |
12 | extern void sx_mgmt_audio_scheduler_close(
13 | void
14 | );
15 |
16 | #endif
17 |
18 |
--------------------------------------------------------------------------------
/mgmt_audio_scheduler/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_audio_scheduler/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common desc pipe audio_sink
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_audio_scheduler/src/sx_mgmt_audio_scheduler.c:
--------------------------------------------------------------------------------
1 | // ========================================================
2 | // Includes
3 | // ========================================================
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "sx_system.h"
16 | #include "sx_pkt.h"
17 | #include "sx_desc.h"
18 | #include "sx_pipe.h"
19 | #include "sx_thread_priority.h"
20 | #include "sx_audio_sink.h"
21 |
22 | // ========================================================
23 | // Constants
24 | // ========================================================
25 |
26 | // ========================================================
27 | // Private Types
28 | // ========================================================
29 |
30 | typedef enum
31 | {
32 | STATE_INACTIVE,
33 | STATE_ACTIVE
34 |
35 | } eSTATE;
36 |
37 | // Decoder control block
38 | typedef struct
39 | {
40 | pthread_t audio_scheduler_thread;
41 | eSTATE state;
42 |
43 | } sMGMT_AUDIO_SCHEDULER_CBLK;
44 |
45 |
46 | // ========================================================
47 | // Private Variables & Functions
48 | // ========================================================
49 |
50 | // Decoder control block.
51 | static sMGMT_AUDIO_SCHEDULER_CBLK f_cblk;
52 |
53 |
54 | static UINT32 audio_total_remaining_ms(
55 | void
56 | )
57 | {
58 |
59 | UINT32 data_left = sx_pipe_len_get(SX_VRDMA_LPCM_SLICE) * 10;
60 | UINT32 queued_left = sx_audio_sink_ms_left_get();
61 |
62 | // printf("total left = %u, data left = %u, queued left = %u\n",
63 | // data_left + queued_left,
64 | // data_left,
65 | // queued_left);
66 |
67 | return (data_left + queued_left);
68 | }
69 |
70 |
71 | static void inline audio_endianness_convert(
72 | UINT16 *temp,
73 | UINT32 samples
74 | )
75 | {
76 | UINT32 i;
77 |
78 |
79 | for(i = 0; i < samples; i++)
80 | {
81 | temp[i] = ntohs(temp[i]);
82 | }
83 | }
84 |
85 |
86 | static void audio_scheduler_slice_dump(
87 | sSX_DESC *slice_head
88 | )
89 | {
90 | UINT8 *curr_ptr;
91 | UINT32 bytes_left;
92 | UINT32 afc;
93 | UINT32 pid;
94 | UINT32 pes_byte_count;
95 | UINT32 payload_size;
96 | UINT32 start_offset;
97 | UINT32 copy_index;
98 | UINT32 samples_left;
99 | UINT32 ms_left;
100 | sSX_DESC *desc;
101 |
102 |
103 | static UINT8 playback_speed = 1;
104 |
105 | ms_left = audio_total_remaining_ms();
106 | if(ms_left > (100 + SX_SYSTEM_DELAY_MS))
107 | {
108 | if(playback_speed != 2)
109 | {
110 | sx_audio_sink_playback_speed_inc();
111 |
112 | playback_speed = 2;
113 | }
114 | }
115 | else if(ms_left < (50 + SX_SYSTEM_DELAY_MS))
116 | {
117 | if(playback_speed != 0)
118 | {
119 | sx_audio_sink_playback_speed_dec();
120 |
121 | playback_speed = 0;
122 | }
123 | }
124 | else
125 | {
126 | if(playback_speed != 1)
127 | {
128 | sx_audio_sink_playback_speed_reset();
129 |
130 | playback_speed = 1;
131 | }
132 | }
133 |
134 | UINT8 *buf = sx_audio_sink_buffer_get();
135 |
136 | copy_index = 0;
137 |
138 | desc = slice_head;
139 | do
140 | {
141 | // Get current.
142 | curr_ptr = desc->data;
143 |
144 | // Get data left.
145 | bytes_left = desc->data_len;
146 | assert(bytes_left > sizeof(sRTP_HDR));
147 |
148 | // Get RTP header.
149 | // sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr;
150 |
151 | // Get TS header.
152 | curr_ptr += sizeof(sRTP_HDR);
153 |
154 | // Get TS bytes left.
155 | bytes_left -= sizeof(sRTP_HDR);
156 | assert((bytes_left % sizeof(sMPEG2_TS)) == 0);
157 |
158 | pes_byte_count = 0;
159 | do
160 | {
161 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
162 |
163 | afc = AFC_GET(ts->hdr);
164 | pid = PID_GET(ts->hdr);
165 |
166 | if(pid == 0x1100)
167 | {
168 | UINT8 stuffing = 0;
169 | if(afc & 0x02)
170 | {
171 | stuffing = 1 + ts->payload.payload[0];
172 | }
173 |
174 | start_offset = stuffing;
175 |
176 | if(PUSI_GET(ts->hdr))
177 | {
178 | start_offset += 20;
179 | }
180 |
181 | payload_size = sizeof(sMPEG2_TS_PAYLOAD) - start_offset;
182 |
183 |
184 | #if 0
185 | if(PUSI_GET(ts->hdr))
186 | {
187 | assert(afc == 0x01);
188 |
189 | start_offset = 20;
190 |
191 | payload_size = (sizeof(sMPEG2_TS_PAYLOAD) - start_offset);
192 | }
193 | else
194 | {
195 | if(afc == 0x01)
196 | {
197 | start_offset = 0;
198 |
199 | payload_size = sizeof(sMPEG2_TS_PAYLOAD);
200 | }
201 | else if(afc == 0x03)
202 | {
203 | start_offset = 1 + ts->payload.payload[0];
204 |
205 | payload_size = sizeof(sMPEG2_TS_PAYLOAD) - start_offset;
206 | }
207 | else
208 | {
209 | assert(0);
210 | }
211 | }
212 | #endif
213 |
214 | // printf("copy 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
215 | // ts->payload.payload[start_offset],
216 | // ts->payload.payload[start_offset + 1],
217 | // ts->payload.payload[start_offset + 2],
218 | // ts->payload.payload[start_offset + 3],
219 | // ts->payload.payload[start_offset + 4],
220 | // ts->payload.payload[start_offset + 5],
221 | // ts->payload.payload[start_offset + 6],
222 | // ts->payload.payload[start_offset + 7]);
223 |
224 | memcpy(&buf[copy_index],
225 | &ts->payload.payload[start_offset],
226 | payload_size);
227 |
228 | copy_index += payload_size;
229 | }
230 |
231 | curr_ptr += sizeof(sMPEG2_TS);
232 | bytes_left -= sizeof(sMPEG2_TS);
233 |
234 | } while (bytes_left > 0);
235 |
236 | desc = desc->next;
237 |
238 | } while (desc != NULL);
239 |
240 | sx_desc_put(slice_head);
241 |
242 | assert(copy_index == 1920);
243 |
244 | // printf("### 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
245 | // buf[0],
246 | // buf[1],
247 | // buf[2],
248 | // buf[3],
249 | // buf[4],
250 | // buf[5],
251 | // buf[6],
252 | // buf[7]);
253 |
254 | audio_endianness_convert((UINT16 *) buf, 960);
255 |
256 | // Push to decoder hardware.
257 | sx_audio_sink_buffer_set(buf, 1920);
258 | }
259 |
260 |
261 | // --------------------------------------------------------
262 | // decoder_thread
263 | // Decoder thread
264 | //
265 | // Description:
266 | // This function defines the decoder thread.
267 | //
268 | void audio_scheduler_thread(
269 | void * arg
270 | )
271 | {
272 | sSX_DESC *desc;
273 |
274 |
275 | while(1)
276 | {
277 | if(f_cblk.state == STATE_INACTIVE)
278 | {
279 | UINT32 len = sx_pipe_len_get(SX_VRDMA_LPCM_SLICE);
280 | if(len > (SX_SYSTEM_DELAY_MS / 10))
281 | {
282 | f_cblk.state = STATE_ACTIVE;
283 |
284 | printf("(audio_scheduler): Transition to active. [len = %u]\n", len);
285 |
286 | goto next_iter;
287 | }
288 | }
289 | else
290 | {
291 | UINT32 data_left_ms = sx_pipe_len_get(SX_VRDMA_LPCM_SLICE) * 10;
292 | UINT32 queued_ms = sx_audio_sink_ms_left_get();
293 |
294 | if((data_left_ms + queued_ms) == 0)
295 | {
296 | f_cblk.state = STATE_INACTIVE;
297 |
298 | printf("(audio_scheduler): Transition to inactive.\n");
299 |
300 | goto next_iter;
301 | }
302 |
303 | if(queued_ms < 200)
304 | {
305 | UINT32 slices_to_queue = (200 - queued_ms + 10) / 10;
306 | do
307 | {
308 | // Get slice.
309 | desc = sx_pipe_get(SX_VRDMA_LPCM_SLICE);
310 | if(desc == NULL)
311 | {
312 | goto next_iter;
313 | }
314 |
315 | // Dump slice.
316 | audio_scheduler_slice_dump(desc);
317 |
318 | slices_to_queue--;
319 |
320 | } while(slices_to_queue > 0);
321 | }
322 | }
323 |
324 | next_iter:
325 |
326 | usleep(5*1000);
327 | }
328 | }
329 |
330 |
331 | // --------------------------------------------------------
332 | // common_resource_init
333 | // Initialize common resources
334 | //
335 | // Description:
336 | // This function initializes the common resources.
337 | //
338 | static void resources_init(
339 | void
340 | )
341 | {
342 | // Initialize decoder hardware.
343 | sx_audio_sink_init();
344 | }
345 |
346 |
347 | // --------------------------------------------------------
348 | // decoder_thread_create
349 | // Creates decoder thread
350 | //
351 | // Description:
352 | // This function creates decoder thread.
353 | //
354 | static void audio_scheduler_thread_create(
355 | void
356 | )
357 | {
358 | sx_thread_create(&f_cblk.audio_scheduler_thread,
359 | &audio_scheduler_thread,
360 | NULL,
361 | MGMT_AUDIO_SCHEDULER_THREAD_PRIORITY);
362 | }
363 |
364 |
365 | // ========================================================
366 | // Public Functions
367 | // ========================================================
368 |
369 | void sx_mgmt_audio_scheduler_init(
370 | void
371 | )
372 | {
373 | // Initialize common resources.
374 | resources_init();
375 |
376 | printf("(audio_scheduler): Init.\n");
377 | }
378 |
379 |
380 | // --------------------------------------------------------
381 | // decoder_open
382 | // Opens decoder
383 | //
384 | void sx_mgmt_audio_scheduler_open(
385 | void
386 | )
387 | {
388 | // Initialize decoder thread.
389 | audio_scheduler_thread_create();
390 |
391 | printf("(audio_scheduler): Open.\n");
392 | }
393 |
394 |
395 | void sx_mgmt_audio_scheduler_close(
396 | void
397 | )
398 | {
399 | }
400 |
--------------------------------------------------------------------------------
/mgmt_ctl/inc/sx_mgmt_ctl.h:
--------------------------------------------------------------------------------
1 | #if !defined(_MGMT_CTL_H_)
2 | #define _MGMT_CTL_H_
3 |
4 | extern void sx_mgmt_ctl_init(
5 | void
6 | );
7 |
8 | extern void sx_mgmt_ctl_open(
9 | void
10 | );
11 |
12 | extern void sx_mgmt_ctl_wait(
13 | void
14 | );
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/mgmt_ctl/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_ctl/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_ctl/src/sx_mgmt_ctl.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "sx_types.h"
11 | #include "sx_mgmt_ctl.h"
12 |
13 | void sx_mgmt_ctl_init(
14 | void
15 | )
16 | {
17 | }
18 |
19 |
20 | int connection_handler(
21 | int connection_fd
22 | )
23 | {
24 | int nbytes;
25 | char buffer[256];
26 |
27 |
28 | printf("mgmt_ctl_wait(): Reading incoming message...\n");
29 |
30 | nbytes = read(connection_fd, buffer, 256);
31 | buffer[nbytes] = 0;
32 |
33 | printf("MESSAGE FROM CLIENT: %s\n", buffer);
34 | // nbytes = snprintf(buffer, 256, "hello from the server");
35 | // write(connection_fd, buffer, nbytes);
36 |
37 | close(connection_fd);
38 |
39 | return 0;
40 | }
41 |
42 |
43 | void sx_mgmt_ctl_wait(
44 | void
45 | )
46 | {
47 | struct sockaddr_un address;
48 | int socket_fd, connection_fd;
49 | socklen_t address_length;
50 | pid_t child;
51 |
52 | socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
53 | if(socket_fd < 0)
54 | {
55 | printf("socket() failed\n");
56 | return;
57 | }
58 |
59 | unlink("./demo_socket");
60 |
61 | /* start with a clean address structure */
62 | memset(&address, 0, sizeof(struct sockaddr_un));
63 |
64 | address.sun_family = AF_UNIX;
65 | snprintf(address.sun_path, 108, "./demo_socket");
66 |
67 | if(bind(socket_fd,
68 | (struct sockaddr *) &address,
69 | sizeof(struct sockaddr_un)) != 0)
70 | {
71 | printf("bind() failed\n");
72 | return;
73 | }
74 |
75 | printf("mgmt_ctl_wait(): Waiting for incoming connection...\n");
76 |
77 | if(listen(socket_fd, 5) != 0)
78 | {
79 | printf("listen() failed\n");
80 | return;
81 | }
82 |
83 | printf("mgmt_ctl_wait(): Accept new connection.\n");
84 |
85 | connection_fd = accept(socket_fd,
86 | (struct sockaddr *) &address,
87 | &address_length);
88 |
89 | /* now inside newly created connection handling process */
90 | connection_handler(connection_fd);
91 |
92 | /* still inside server process */
93 | close(connection_fd);
94 |
95 | close(socket_fd);
96 | unlink("./demo_socket");
97 | }
98 |
--------------------------------------------------------------------------------
/mgmt_data/inc/sx_mgmt_data.h:
--------------------------------------------------------------------------------
1 | #if !defined(_MGMT_DATA_H_)
2 | #define _MGMT_DATA_H_
3 |
4 | extern void sx_mgmt_data_init(
5 | void
6 | );
7 |
8 | extern void sx_mgmt_data_open(
9 | void
10 | );
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/mgmt_data/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_data/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common desc pipe
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_data/src/sx_mgmt_data.c:
--------------------------------------------------------------------------------
1 | // ========================================================
2 | // Includes
3 | // ========================================================
4 |
5 | #include
6 | #include
7 |
8 | #include "sx_desc.h"
9 | #include "sx_udp.h"
10 | #include "sx_pkt.h"
11 | #include "sx_thread.h"
12 | #include "sx_pipe.h"
13 |
14 | #include "sx_mgmt_data.h"
15 |
16 | // ========================================================
17 | // Constants
18 | // ========================================================
19 |
20 | // ========================================================
21 | // Private Types
22 | // ========================================================
23 |
24 | // --------------------------------------------------------
25 | // sMGMT_DATA_CBLK
26 | // Control block structure.
27 | //
28 | typedef struct
29 | {
30 | pthread_t pkt_rx_thread; ///< Packet receive thread
31 | SBOX_UDP_ID udp_sock; ///< UDP socket
32 | unsigned int rx_pkt; ///< Number of received packet
33 |
34 | } sMGMT_DATA_CBLK;
35 |
36 | // ========================================================
37 | // Private Variables & Functions
38 | // ========================================================
39 |
40 | // Define local control block.
41 | static sMGMT_DATA_CBLK f_cblk;
42 |
43 | // --------------------------------------------------------
44 | // pkt_rx_thread
45 | // Create packet receive thread.
46 | //
47 | static void pkt_rx_thread(
48 | void * arg
49 | )
50 | {
51 | sPI_PORTAL_PKT *pkt;
52 | UINT16 last_seq_num;
53 | UINT16 curr_seq_num;
54 |
55 |
56 | while(1)
57 | {
58 | // Malloc packet to hold data.
59 | pkt = malloc(sizeof(sPI_PORTAL_PKT));
60 |
61 | // Receive packet.
62 | UINT32 pkt_len = sizeof(sPI_PORTAL_PKT);
63 |
64 | // -----------------------------
65 | // Wait for packet.
66 | // -----------------------------
67 |
68 | sx_udp_recv(f_cblk.udp_sock, (char *) pkt, &pkt_len);
69 |
70 | // -----------------------------
71 | // Check for missing packets.
72 | // -----------------------------
73 |
74 | sRTP_HDR *rtp_hdr = (sRTP_HDR *) pkt;
75 |
76 | curr_seq_num = ntohs(rtp_hdr->sequence_num);
77 | if((UINT16) (last_seq_num + 1) != curr_seq_num)
78 | {
79 | printf("(mgmt_data): last_seq_num = %u, curr_seq_num = %u, lost %u pkts.\n",
80 | last_seq_num,
81 | curr_seq_num,
82 | curr_seq_num - (last_seq_num + 1));
83 | }
84 |
85 | // Cache last sequence number.
86 | last_seq_num = curr_seq_num;
87 |
88 | // -----------------------------
89 | // Push packet to process queue.
90 | // -----------------------------
91 |
92 | sSX_DESC *desc = sx_desc_get();
93 |
94 | desc->data = (void *) pkt;
95 | desc->data_len = pkt_len;
96 |
97 | sx_pipe_put(SX_VRDMA_PKT_QUEUE, desc);
98 |
99 | f_cblk.rx_pkt++;
100 | }
101 | }
102 |
103 |
104 | // --------------------------------------------------------
105 | // data_rx_thread_create
106 | // Create data RX thread
107 | //
108 | static void pkt_rx_thread_create(
109 | void
110 | )
111 | {
112 | sx_thread_create(&f_cblk.pkt_rx_thread, &pkt_rx_thread, NULL, MGMT_DATA_RX_THREAD_PRIORITY);
113 | }
114 |
115 |
116 | // ========================================================
117 | // Public Functions
118 | // ========================================================
119 |
120 | // --------------------------------------------------------
121 | // sx_mgmt_data_init
122 | // Initialize data manager.
123 | //
124 | void sx_mgmt_data_init(
125 | void
126 | )
127 | {
128 | f_cblk.udp_sock = sx_udp_create(50000);
129 |
130 | printf("(mgmt_data): mgmt_data_init(): Initialized.\n");
131 | }
132 |
133 |
134 | // --------------------------------------------------------
135 | // sx_mgmt_data_open
136 | // Open data manager on session boundary.
137 | //
138 | void sx_mgmt_data_open(
139 | void
140 | )
141 | {
142 | pkt_rx_thread_create();
143 |
144 | printf("(mgmt_data_open): Opened.\n");
145 | }
146 |
147 |
--------------------------------------------------------------------------------
/mgmt_env/inc/sx_mgmt_env.h:
--------------------------------------------------------------------------------
1 | #if !defined(_MGMT_ENV_H_)
2 | #define _MGMT_ENV_H_
3 |
4 | #include "sx_types.h"
5 |
6 | typedef enum
7 | {
8 | MGMT_ENV_VAR_WIDTH,
9 | MGMT_ENV_VAR_HEIGHT,
10 | MGMT_ENV_VAR_SESSION_WIDTH,
11 | MGMT_ENV_VAR_SESSION_HEIGHT,
12 |
13 | MGMT_ENV_VAR_MAX
14 |
15 | } eMGMT_ENV_VAR;
16 |
17 | extern void sx_mgmt_env_init(
18 | void
19 | );
20 |
21 | extern void sx_mgmt_env_open(
22 | void
23 | );
24 |
25 | extern UINT32 sx_mgmt_env_get(
26 | eMGMT_ENV_VAR var
27 | );
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/mgmt_env/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_env/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_env/src/sx_mgmt_env.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "sx_types.h"
6 | #include "sx_mgmt_env.h"
7 |
8 | typedef struct
9 | {
10 | eMGMT_ENV_VAR var;
11 | char *str;
12 |
13 | } sMGMT_ENV_VAR_ENTRY;
14 |
15 |
16 | static sMGMT_ENV_VAR_ENTRY f_env_var_table[] =
17 | {
18 | { MGMT_ENV_VAR_WIDTH, "displayWidth" },
19 | { MGMT_ENV_VAR_HEIGHT, "displayHeight" },
20 | { MGMT_ENV_VAR_SESSION_WIDTH, "sessionWidth" },
21 | { MGMT_ENV_VAR_SESSION_HEIGHT, "sessionHeight" }
22 | };
23 | #define MGMT_ENV_VAR_TABLE_SIZE (sizeof(f_env_var_table)/sizeof(f_env_var_table[0]))
24 |
25 |
26 | static UINT32 f_env_vars[MGMT_ENV_VAR_MAX] = {0};
27 |
28 |
29 | void sx_mgmt_env_init(
30 | void
31 | )
32 | {
33 | FILE * read_ptr = fopen("env.txt", "r");
34 | assert(read_ptr != NULL);
35 |
36 | char line[128];
37 | UINT32 i;
38 | UINT8 found;
39 | UINT32 value;
40 |
41 | while(fgets(line, sizeof(line), read_ptr) != NULL)
42 | {
43 | line[strlen(line) - 1] = 0;
44 |
45 | found = 0;
46 |
47 | for(i = 0; i < MGMT_ENV_VAR_TABLE_SIZE; i++)
48 | {
49 | if(strstr(line, f_env_var_table[i].str) != NULL)
50 | {
51 | printf("found!!\n");
52 |
53 | found = 1;
54 |
55 | break;
56 | }
57 | }
58 |
59 | if(found)
60 | {
61 | // char var_name[20];
62 |
63 | // printf("line= %s\n", line);
64 |
65 | sscanf(line, "%*s %d", &value);
66 |
67 | f_env_vars[f_env_var_table[i].var] = value;
68 |
69 | printf("value = %u\n", value);
70 | }
71 | }
72 | }
73 |
74 |
75 | void sx_mgmt_env_open(
76 | void
77 | )
78 | {
79 |
80 | }
81 |
82 |
83 | UINT32 sx_mgmt_env_get(
84 | eMGMT_ENV_VAR var
85 | )
86 | {
87 | printf("(sx_mgmt_env_get(): var = %u\n", f_env_vars[var]);
88 |
89 | return f_env_vars[var];
90 | }
91 |
--------------------------------------------------------------------------------
/mgmt_m2ts_decoder/inc/sx_mgmt_m2ts_decoder.h:
--------------------------------------------------------------------------------
1 | #if !defined(_MGMT_M2TS_DECODER_H_)
2 | #define _MGMT_M2TS_DECODER_H_
3 |
4 | extern void sx_mgmt_m2ts_decoder_init(
5 | void
6 | );
7 |
8 | extern void sx_mgmt_m2ts_decoder_open(
9 | void
10 | );
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/mgmt_m2ts_decoder/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_m2ts_decoder/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common pipe desc
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_m2ts_decoder/src/sx_mgmt_m2ts_decoder.c:
--------------------------------------------------------------------------------
1 | // ========================================================
2 | // Includes
3 | // ========================================================
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 | #include
17 | #include
18 |
19 | #include "sx_udp.h"
20 | #include "sx_pkt.h"
21 | #include "sx_desc.h"
22 | #include "sx_thread.h"
23 | #include "sx_queue.h"
24 |
25 | #include "sx_types.h"
26 | #include "sx_pipe.h"
27 |
28 | // ========================================================
29 | // Constants
30 | // ========================================================
31 |
32 | // #define LOOPBACK
33 |
34 | // ========================================================
35 | // Private Types
36 | // ========================================================
37 |
38 | typedef struct
39 | {
40 | pthread_t pkt_process_thread;
41 |
42 | } sMGMT_DATA_CBLK;
43 |
44 |
45 | // ========================================================
46 | // Private Variables & Functions
47 | // ========================================================
48 |
49 | static sMGMT_DATA_CBLK f_cblk;
50 |
51 | typedef enum
52 | {
53 | PKT_TYPE_AUDIO,
54 | PKT_TYPE_VIDEO,
55 | PKT_TYPE_NULL
56 |
57 | } ePKT_TYPE;
58 |
59 |
60 | static UINT64 pcr_get(
61 | sSX_DESC *desc
62 | )
63 | {
64 | UINT8 *curr_ptr;
65 | UINT32 bytes_left;
66 |
67 | static UINT64 last_pcr_ms;
68 |
69 |
70 | // Get current.
71 | curr_ptr = desc->data;
72 |
73 | // Get data left.
74 | bytes_left = desc->data_len;
75 | assert(bytes_left > sizeof(sRTP_HDR));
76 |
77 | // Get TS header.
78 | curr_ptr += sizeof(sRTP_HDR);
79 |
80 | // Get TS bytes left.
81 | bytes_left -= sizeof(sRTP_HDR);
82 | assert((bytes_left % sizeof(sMPEG2_TS)) == 0);
83 |
84 | do
85 | {
86 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
87 | UINT16 pid = PID_GET(ts->hdr);
88 |
89 | if(pid == 0x1000)
90 | {
91 | curr_ptr += (sizeof(sMPEG2_TS_HDR) + 2);
92 |
93 | UINT64 pcr = 0;
94 | UINT32 i;
95 | for(i = 0; i < 6; i++)
96 | {
97 | pcr = ((pcr << 8) | curr_ptr[i]);
98 | }
99 |
100 | // printf("(pcr_get): curr_ptr: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
101 | // curr_ptr[0],
102 | // curr_ptr[1],
103 | // curr_ptr[2],
104 | // curr_ptr[3],
105 | // curr_ptr[4],
106 | // curr_ptr[5]);
107 | //
108 | // printf("(pcr_get): pcr: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
109 | // ((UINT8 *) &pcr)[0],
110 | // ((UINT8 *) &pcr)[1],
111 | // ((UINT8 *) &pcr)[2],
112 | // ((UINT8 *) &pcr)[3],
113 | // ((UINT8 *) &pcr)[4],
114 | // ((UINT8 *) &pcr)[5]);
115 |
116 | UINT64 pcr_base = (pcr >> (9 + 6));
117 |
118 | UINT64 pcr_ext = pcr & (0x1FF);
119 |
120 | pcr = pcr_base * 300 + pcr_ext;
121 |
122 | UINT64 pcr_ms = pcr / 27000;
123 |
124 | // printf("(pcr_get): pcr = %llu, pcr_ms = %llu, delta = %u\n",
125 | // pcr,
126 | // pcr_ms,
127 | // (UINT32) (pcr_ms - last_pcr_ms));
128 |
129 | last_pcr_ms = pcr_ms;
130 |
131 | return pcr_ms;
132 | }
133 |
134 | bytes_left -= sizeof(sMPEG2_TS);
135 | curr_ptr += sizeof(sMPEG2_TS);
136 |
137 | } while (bytes_left > 0);
138 |
139 | return 0;
140 | }
141 |
142 |
143 | static ePKT_TYPE pkt_type_get(
144 | sSX_DESC *desc
145 | )
146 | {
147 | UINT8 *curr_ptr;
148 | UINT32 bytes_left;
149 |
150 |
151 | // Get current.
152 | curr_ptr = desc->data;
153 |
154 | // Get data left.
155 | bytes_left = desc->data_len;
156 | assert(bytes_left > sizeof(sRTP_HDR));
157 |
158 | // Get TS header.
159 | curr_ptr += sizeof(sRTP_HDR);
160 |
161 | // Get TS bytes left.
162 | bytes_left -= sizeof(sRTP_HDR);
163 | assert((bytes_left % sizeof(sMPEG2_TS)) == 0);
164 |
165 | // printf("(mgmt_m2ts): pkt_type_get() invoked!\n");
166 |
167 | do
168 | {
169 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
170 | UINT16 pid = PID_GET(ts->hdr);
171 |
172 | #if 0
173 | printf("(mgmt_m2ts): 0x%x 0x%x 0x%x 0x%x\n",
174 | ts->hdr.sync_byte,
175 | ts->hdr.tei_pusi_tp_pid1,
176 | ts->hdr.pid2,
177 | ts->hdr.tsc_afc_cc);
178 |
179 | printf("(mgmt_m2ts): pid = 0x%.4x\n", pid);
180 | #endif
181 |
182 | if(pid == 0x1011)
183 | {
184 | return PKT_TYPE_VIDEO;
185 | }
186 | else if(pid == 0x1100)
187 | {
188 | return PKT_TYPE_AUDIO;
189 | }
190 |
191 | bytes_left -= sizeof(sMPEG2_TS);
192 | curr_ptr += sizeof(sMPEG2_TS);
193 |
194 | } while (bytes_left > 0);
195 |
196 | return PKT_TYPE_NULL;
197 | }
198 |
199 |
200 | static void pkt_process_thread(
201 | void * arg
202 | )
203 | {
204 | SX_QUEUE *queue;
205 | sSX_DESC *desc;
206 | sSX_DESC *h264_desc;
207 | sSX_DESC *lpcm_desc;
208 | UINT32 bytes_left;
209 |
210 |
211 | while(1)
212 | {
213 | do
214 | {
215 | desc = sx_pipe_get(SX_VRDMA_PKT_QUEUE);
216 | if(desc == NULL)
217 | {
218 | break;
219 | }
220 |
221 | // Get data left.
222 | bytes_left = desc->data_len;
223 | assert(bytes_left > sizeof(sRTP_HDR));
224 |
225 | // ------------------------
226 | // Get and push program reference time.
227 | // ------------------------
228 |
229 | UINT64 pcr_ms = pcr_get(desc);
230 | if(pcr_ms > 0)
231 | {
232 | sSX_DESC *new_desc = sx_desc_get();
233 |
234 | sSLICE_HDR *hdr = malloc(sizeof(sSLICE_HDR));
235 | assert(hdr != NULL);
236 |
237 | hdr->type = SLICE_TYPE_PCR;
238 | hdr->timestamp = pcr_ms;
239 |
240 | new_desc->data = (void *) hdr;
241 | new_desc->data_len = sizeof(sSLICE_HDR);
242 |
243 | sx_pipe_put(SX_VRDMA_PCR, new_desc);
244 | }
245 |
246 | // ------------------------
247 | // Get and push media packet.
248 | // ------------------------
249 |
250 | ePKT_TYPE pkt_type = pkt_type_get(desc);
251 | switch(pkt_type)
252 | {
253 | case PKT_TYPE_VIDEO:
254 | {
255 | sx_pipe_put(SX_VRDMA_VIDEO_PKT_QUEUE, desc);
256 | break;
257 | }
258 | case PKT_TYPE_AUDIO:
259 | {
260 | sx_pipe_put(SX_VRDMA_LPCM, desc);
261 | break;
262 | }
263 | case PKT_TYPE_NULL:
264 | {
265 | sx_desc_put(desc);
266 | break;
267 | }
268 | default:
269 | {
270 | assert(0);
271 | break;
272 | }
273 | }
274 |
275 | } while(1);
276 |
277 | usleep(1*1000);
278 | }
279 | }
280 |
281 |
282 | static void pkt_process_thread_create(
283 | void
284 | )
285 | {
286 | sx_thread_create(&f_cblk.pkt_process_thread, &pkt_process_thread, NULL, MGMT_M2TS_PKT_PROCESS_THREAD_PRIORITY);
287 | }
288 |
289 |
290 | // ========================================================
291 | // Public Functions
292 | // ========================================================
293 |
294 | // --------------------------------------------------------
295 | // hole_punching_client_init
296 | // Opens decoder
297 | //
298 | void sx_mgmt_m2ts_decoder_init(
299 | void
300 | )
301 | {
302 | printf("(mgmt_m2ts): sx_mgmt_m2ts_decoder_init(): Initialized.\n");
303 | }
304 |
305 |
306 | // --------------------------------------------------------
307 | // mgmt_data_open
308 | // Open data manager on session boundary.
309 | //
310 | void sx_mgmt_m2ts_decoder_open(
311 | void
312 | )
313 | {
314 | pkt_process_thread_create();
315 |
316 | printf("(mgmt_m2ts_decoder_open): sx_mgmt_m2ts_decoder_open(): Invoked.\n");
317 | }
318 |
--------------------------------------------------------------------------------
/mgmt_sys/inc/sx_mgmt_sys.h:
--------------------------------------------------------------------------------
1 | #if !defined(MGMT_SYS_H)
2 | #define MGMT_SYS_H
3 |
4 | typedef enum
5 | {
6 | MGMT_SYS_TYPE_ENCODER,
7 | MGMT_SYS_TYPE_DECODER
8 |
9 | } eMGMT_SYS_TYPE;
10 |
11 | extern void mgmt_sys_open(
12 | void
13 | );
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/mgmt_sys/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_sys/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common mgmt_m2ts_decoder mgmt_video_decoder mgmt_data mgmt_env mgmt_ctl
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_sys/src/sx_mgmt_sys.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "sx_thread_priority.h"
9 | #include "sx_mgmt_sys.h"
10 | #include "sx_mgmt_m2ts_decoder.h"
11 | #include "sx_mgmt_video_decoder.h"
12 | #include "sx_mgmt_data.h"
13 | #include "sx_mgmt_ctl.h"
14 |
15 |
16 | static pthread_t f_mgmt_sys_thread;
17 |
18 | static void resource_init(
19 | void
20 | )
21 | {
22 | #if 0
23 | struct mq_attr queue_attr;
24 |
25 | // Initialize queue attributes.
26 | queue_attr.mq_flags = 0;
27 | queue_attr.mq_maxmsg = 10;
28 | queue_attr.mq_msgsize = sizeof(sMGMT_SYS_MSG);
29 | queue_attr.mq_curmsgs = 0;
30 |
31 | // Create message queue.
32 | f_cblk.mgmt_sys_msg_queue = mq_open(MGMT_SYS_MSG_QUEUE_NAME, O_CREAT | O_RDWR, 0644, &queue_attr);
33 | assert(f_cblk.mgmt_sys_msg_queue > 0);
34 | #endif
35 | }
36 |
37 |
38 | static void wait_forever(
39 | void
40 | )
41 | {
42 | pthread_join(f_mgmt_sys_thread, NULL);
43 | }
44 |
45 |
46 | void mgmt_sys_init(
47 | void
48 | )
49 | {
50 | // Initialize system manager.
51 | resource_init();
52 |
53 | // Initialize VRDMA.
54 | sx_pipe_init();
55 |
56 | // sx_mgmt_env_init();
57 |
58 | // Initialize Data manager.
59 | sx_mgmt_data_init();
60 |
61 | // Initialize m2ts decoder.
62 | sx_mgmt_m2ts_decoder_init();
63 |
64 | // Initialize video decoder module.
65 | sx_mgmt_video_decoder_init();
66 |
67 | sx_mgmt_video_scheduler_init();
68 |
69 | // Initialize audio decoder module.
70 | sx_mgmt_audio_decoder_init();
71 |
72 | sx_mgmt_audio_scheduler_init();
73 |
74 | printf("(mgmt_sys): (mgmt_sys_init): Done.\n");
75 | }
76 |
77 |
78 | static void mgmt_sys_thread(
79 | void * arg
80 | )
81 | {
82 | do
83 | {
84 | usleep(1*1000*1000);
85 |
86 | } while(1);
87 | }
88 |
89 |
90 | void mgmt_sys_open(
91 | void
92 | )
93 | {
94 | // Initialize Data manager.
95 | sx_mgmt_data_open();
96 |
97 | // Initialize m2ts decoder.
98 | sx_mgmt_m2ts_decoder_open();
99 |
100 | // Initialize video decoder module.
101 | sx_mgmt_video_decoder_open();
102 |
103 | // Initialize video scheduler.
104 | sx_mgmt_video_scheduler_open();
105 |
106 | // Initialize video decoder module.
107 | sx_mgmt_audio_decoder_open();
108 |
109 | // Initialize audio scheduler.
110 | sx_mgmt_audio_scheduler_open();
111 |
112 | printf("(mgmt_sys): (mgmt_sys_open): Done.\n");
113 |
114 | sx_thread_create(&f_mgmt_sys_thread, &mgmt_sys_thread, NULL, MGMT_SYS_THREAD_PRIORITY);
115 |
116 | // Wait forever.
117 | wait_forever();
118 | // sx_mgmt_ctl_wait();
119 | }
120 |
--------------------------------------------------------------------------------
/mgmt_video_decoder/inc/sx_mgmt_video_decoder.h:
--------------------------------------------------------------------------------
1 | #if !defined(SX_MGMT_VIDEO_DECODER_H)
2 | #define SX_MGMT_VIDEO_DECODER_H
3 |
4 | extern void sx_mgmt_video_decoder_init(
5 | void
6 | );
7 |
8 | extern void sx_mgmt_video_decoder_open(
9 | void
10 | );
11 |
12 | extern void sx_mgmt_video_decoder_close(
13 | void
14 | );
15 |
16 | #endif
17 |
18 |
--------------------------------------------------------------------------------
/mgmt_video_decoder/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_video_decoder/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common desc pipe video_sink
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_video_decoder/src/sx_mgmt_video_decoder.c:
--------------------------------------------------------------------------------
1 | // ========================================================
2 | // Includes
3 | // ========================================================
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "sx_pkt.h"
16 | #include "sx_desc.h"
17 | #include "sx_pipe.h"
18 | #include "sx_thread_priority.h"
19 | #include "sx_video_sink.h"
20 |
21 | // ========================================================
22 | // Constants
23 | // ========================================================
24 |
25 | // ========================================================
26 | // Private Types
27 | // ========================================================
28 |
29 | typedef struct
30 | {
31 | sSX_DESC *head;
32 | sSX_DESC *tail;
33 |
34 | } sSLICE_CHAIN;
35 |
36 | // Decoder control block
37 | typedef struct
38 | {
39 | pthread_t decoder_thread;
40 | UINT32 look_for_new_slice;
41 | UINT32 pes_payload_curr_len;
42 | UINT32 last_cc;
43 | UINT32 slice_pkt_count;
44 | UINT64 slice_pts_ms;
45 | UINT64 slice_count;
46 | UINT16 last_seq_num;
47 | sSLICE_CHAIN slice_chain;
48 |
49 | } sDECODER_CBLK;
50 |
51 |
52 | // ========================================================
53 | // Private Variables & Functions
54 | // ========================================================
55 |
56 | // Decoder control block.
57 | static sDECODER_CBLK f_cblk;
58 |
59 | static sSX_DESC * slice_get(
60 | void
61 | )
62 | {
63 | sSX_DESC *head;
64 |
65 |
66 | head = f_cblk.slice_chain.head;
67 |
68 | f_cblk.slice_chain.head = NULL;
69 | f_cblk.slice_chain.tail = NULL;
70 |
71 | // printf("slice_get() invoked\n");
72 |
73 | return head;
74 | }
75 |
76 |
77 | /**
78 | * Dumps a slice onto the queue.
79 | *
80 | * @param pts_ms
81 | * @param slice_head
82 | */
83 | static void video_decoder_slice_dump(
84 | UINT64 pts_ms,
85 | sSX_DESC *slice_head
86 | )
87 | {
88 | sSLICE_HDR *hdr = malloc(sizeof(sSLICE_HDR));
89 | assert(hdr != NULL);
90 |
91 | hdr->type = SLICE_TYPE_SLICE;
92 | hdr->timestamp = pts_ms;
93 |
94 | sSX_DESC *new_desc = sx_desc_get();
95 |
96 | new_desc->data = (void *) hdr;
97 | new_desc->data_len = sizeof(sSLICE_HDR);
98 |
99 | new_desc->next = slice_head;
100 |
101 | sx_pipe_put(SX_VRDMA_SLICE, new_desc);
102 | }
103 |
104 |
105 | /**
106 | * Drops a given slice.
107 | */
108 | static void slice_drop(
109 | void
110 | )
111 | {
112 | sSX_DESC *curr;
113 | sSX_DESC *next;
114 |
115 |
116 | // Drop slice.
117 | sx_desc_put(f_cblk.slice_chain.head);
118 |
119 | // Reset head and tail.
120 | f_cblk.slice_chain.head = NULL;
121 | f_cblk.slice_chain.tail = NULL;
122 |
123 | printf("slice_dropped() invoked\n");
124 | }
125 |
126 |
127 | /**
128 | * Add a packet to a slice chain.
129 | *
130 | * @param desc
131 | */
132 | static void slice_pkt_add(
133 | sSX_DESC *desc
134 | )
135 | {
136 | assert(desc != NULL);
137 |
138 |
139 | if(f_cblk.slice_chain.head == NULL)
140 | {
141 | f_cblk.slice_chain.head = desc;
142 | f_cblk.slice_chain.tail = desc;
143 |
144 | return;
145 | }
146 |
147 | // Append to tail.
148 | f_cblk.slice_chain.tail->next = desc;
149 |
150 | // Update tail.
151 | f_cblk.slice_chain.tail = desc;
152 | }
153 |
154 |
155 | /**
156 | * Interpret mpeg 2 transport stream data.
157 | *
158 | * @param desc
159 | * @param pes_payload_size
160 | * @param cc_start
161 | * @param cc_end
162 | */
163 | static void m2ts_data_interpret(
164 | sSX_DESC *desc,
165 | UINT32 *pes_payload_size,
166 | UINT8 *cc_start,
167 | UINT8 *cc_end
168 | )
169 | {
170 | UINT8 *curr_ptr;
171 | UINT32 bytes_left;
172 | UINT32 afc;
173 | UINT32 pid;
174 | UINT32 pes_byte_count;
175 | UINT32 payload_size;
176 | UINT8 cc;
177 |
178 |
179 | // Get current.
180 | curr_ptr = desc->data;
181 |
182 | // Get data left.
183 | bytes_left = desc->data_len;
184 | assert(bytes_left > sizeof(sRTP_HDR));
185 |
186 | // Get RTP header.
187 | // sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr;
188 |
189 | // Get TS header.
190 | curr_ptr += sizeof(sRTP_HDR);
191 |
192 | // Get TS bytes left.
193 | bytes_left -= sizeof(sRTP_HDR);
194 | assert((bytes_left % sizeof(sMPEG2_TS)) == 0);
195 |
196 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
197 |
198 | UINT8 first_chunk = 1;
199 |
200 | pes_byte_count = 0;
201 | do
202 | {
203 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
204 | afc = AFC_GET(ts->hdr);
205 | pid = PID_GET(ts->hdr);
206 |
207 | if(pid == 0x1011)
208 | {
209 | cc = CC_GET(ts->hdr);
210 | if(first_chunk)
211 | {
212 | *cc_start = cc;
213 |
214 | first_chunk = 0;
215 | }
216 |
217 | if(PUSI_GET(ts->hdr))
218 | {
219 | // assert(afc == 0x03);
220 |
221 | // printf("### 0x%x 0x%x 0x%x 0x%x\n",
222 | // ts->payload.payload[14],
223 | // ts->payload.payload[15],
224 | // ts->payload.payload[16],
225 | // ts->payload.payload[17]);
226 |
227 | payload_size = (sizeof(sMPEG2_TS_PAYLOAD) - 14);
228 | }
229 | else
230 | {
231 | if(afc == 0x01)
232 | {
233 | payload_size = sizeof(sMPEG2_TS_PAYLOAD);
234 | }
235 | else if(afc == 0x03)
236 | {
237 | payload_size = sizeof(sMPEG2_TS_PAYLOAD) - 1 - ts->payload.payload[0];
238 | }
239 | else
240 | {
241 | assert(0);
242 | }
243 | }
244 |
245 | pes_byte_count += payload_size;
246 | }
247 |
248 | bytes_left -= sizeof(sMPEG2_TS);
249 | curr_ptr += sizeof(sMPEG2_TS);
250 |
251 | } while (bytes_left > 0);
252 |
253 | *cc_end = cc;
254 | *pes_payload_size = pes_byte_count;
255 | }
256 |
257 |
258 | /**
259 | * Find the slice start.
260 | *
261 | * @param desc
262 | * @param pes_payload_size
263 | * @param pts_ms
264 | * @return
265 | */
266 | static UINT8 slice_start_find(
267 | sSX_DESC *desc,
268 | UINT32 *pes_payload_size,
269 | UINT64 *pts_ms
270 | )
271 | {
272 | UINT8 *curr_ptr;
273 | UINT32 bytes_left;
274 | sMPEG2_TS *ts;
275 | UINT32 pid;
276 | UINT32 afc;
277 |
278 |
279 | // Get current.
280 | curr_ptr = desc->data;
281 |
282 | // Get data left.
283 | bytes_left = desc->data_len;
284 | assert(bytes_left > sizeof(sRTP_HDR));
285 |
286 | // Get RTP header.
287 | sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr;
288 |
289 | // Get TS header.
290 | curr_ptr += sizeof(sRTP_HDR);
291 |
292 | // Get TS bytes left.
293 | bytes_left -= sizeof(sRTP_HDR);
294 | assert((bytes_left % sizeof(sMPEG2_TS)) == 0);
295 |
296 | do
297 | {
298 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
299 |
300 | afc = AFC_GET(ts->hdr);
301 | pid = PID_GET(ts->hdr);
302 |
303 | if(PUSI_GET(ts->hdr) && (pid == 0x1011))
304 | {
305 | curr_ptr = &ts->payload.payload[0];
306 |
307 | UINT8 adaptation_field_len = 0;
308 | if(afc & 0x02)
309 | {
310 | // adaption field is present.
311 | //
312 | // determine how many bytes to skip.
313 |
314 | adaptation_field_len = 1 + *curr_ptr;
315 | }
316 |
317 | // Skip 'adaptation field length' field.
318 | curr_ptr += adaptation_field_len;
319 |
320 | // Skip adaptation field length.
321 | curr_ptr += sizeof(sPES);
322 |
323 | sPES_EXT *pes_ext = (sPES_EXT *) curr_ptr;
324 |
325 | UINT16 len = ntohs(pes_ext->length);
326 | if(len > 0)
327 | {
328 | *pes_payload_size = len - 8;
329 | }
330 | else
331 | {
332 | *pes_payload_size = 0;
333 | }
334 |
335 | curr_ptr += sizeof(sPES_EXT);
336 |
337 | // The adaptation field is present in the TS header of
338 | // Sony Xperia. Due to this initial byte of PES payload
339 | // becomes 0x0a
340 | if((*curr_ptr != 0x05) && (*curr_ptr != 0x0a))
341 | {
342 | printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
343 | ((UINT8 *) ts)[0],
344 | ((UINT8 *) ts)[1],
345 | ((UINT8 *) ts)[2],
346 | ((UINT8 *) ts)[3],
347 | ((UINT8 *) ts)[4],
348 | ((UINT8 *) ts)[5],
349 | ((UINT8 *) ts)[6],
350 | ((UINT8 *) ts)[7]);
351 |
352 | printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
353 | ((UINT8 *) ts)[8],
354 | ((UINT8 *) ts)[9],
355 | ((UINT8 *) ts)[10],
356 | ((UINT8 *) ts)[11],
357 | ((UINT8 *) ts)[12],
358 | ((UINT8 *) ts)[13],
359 | ((UINT8 *) ts)[14],
360 | ((UINT8 *) ts)[15]);
361 |
362 | printf("*curr_ptr = 0x%x, delta = %u\n",
363 | *curr_ptr,
364 | (UINT8 *)curr_ptr - (UINT8 *) ts);
365 |
366 | // Consistency check.
367 | assert(0);
368 | }
369 |
370 | curr_ptr++;
371 |
372 | UINT32 i;
373 | UINT64 pts;
374 | pts = 0;
375 | for(i = 0; i < 5; i++)
376 | {
377 | pts = ((pts << 8) | curr_ptr[i]);
378 | }
379 |
380 | UINT64 pts_hz;
381 | UINT64 mask;
382 |
383 | pts_hz = 0;
384 |
385 | mask = 0x0007;
386 | pts_hz |= (pts & (mask << 33)) >> 3;
387 |
388 | mask = 0x7fff;
389 | pts_hz |= (pts & (mask << 17)) >> 2;
390 |
391 | mask = 0x7fff;
392 | pts_hz |= (pts & (mask << 1)) >> 1;
393 |
394 | // Convert to ms.
395 | *pts_ms = pts_hz / 90;
396 |
397 | return 1;
398 | }
399 |
400 | curr_ptr += sizeof(sMPEG2_TS);
401 | bytes_left -= sizeof(sMPEG2_TS);
402 |
403 | } while (bytes_left > 0);
404 |
405 | return 0;
406 | }
407 |
408 |
409 | // --------------------------------------------------------
410 | // decoder_thread
411 | // Decoder thread
412 | //
413 | // Description:
414 | // This function defines the decoder thread.
415 | //
416 | void video_decoder_thread(
417 | void * arg
418 | )
419 | {
420 | sSX_DESC *desc;
421 | sSX_DESC *slice_start;
422 | sSX_DESC *slice_end;
423 | UINT8 *curr_ptr;
424 | UINT32 bytes_left;
425 | sMPEG2_TS *ts;
426 | UINT32 pes_payload_len;
427 | UINT8 slice_start_found;
428 | UINT8 cc_start;
429 | UINT8 cc_end;
430 | UINT32 pes_payload_size;
431 |
432 |
433 | while(1)
434 | {
435 | do
436 | {
437 | desc = sx_pipe_get(SX_VRDMA_VIDEO_PKT_QUEUE);
438 | if(desc == NULL)
439 | {
440 | break;
441 | }
442 |
443 | // Get current.
444 | curr_ptr = desc->data;
445 |
446 | // Get data left.
447 | bytes_left = desc->data_len;
448 | assert(bytes_left > sizeof(sRTP_HDR));
449 |
450 | // Get RTP header.
451 | sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr;
452 |
453 | // Get TS header.
454 | curr_ptr += sizeof(sRTP_HDR);
455 | ts = (sMPEG2_TS *) curr_ptr;
456 |
457 | // Always Look for slice start.
458 | UINT64 pts_ms;
459 | slice_start_found = slice_start_find(desc, &pes_payload_len, &pts_ms);
460 |
461 | if(f_cblk.look_for_new_slice)
462 | {
463 | if(!slice_start_found)
464 | {
465 | // Looking for a new slice but didn't find a slice start.
466 | //
467 | // Retry with the next packet.
468 |
469 | goto cleanup;
470 | }
471 |
472 | // Found new slice. Keep going.
473 | f_cblk.look_for_new_slice = 0;
474 | }
475 |
476 | if(slice_start_found)
477 | {
478 | // printf("New slice: RTP seq = %u, pts = %llu\n",
479 | // pts_ms,
480 | // ntohs(rtp_hdr->sequence_num));
481 |
482 | if(f_cblk.slice_count == 0)
483 | {
484 | f_cblk.slice_pts_ms = pts_ms;
485 | }
486 |
487 | if(f_cblk.slice_pkt_count > 0)
488 | {
489 | // printf("slice pkt count = %u, pes_payload_size = %u\n",
490 | // f_cblk.slice_pkt_count,
491 | // f_cblk.pes_payload_curr_len);
492 |
493 | // If we already have a chain and found a slice start,
494 | // dump the slice.
495 | video_decoder_slice_dump(f_cblk.slice_pts_ms, slice_get());
496 |
497 | // Reset slice packet count.
498 | f_cblk.slice_pkt_count = 0;
499 | f_cblk.pes_payload_curr_len = 0;
500 | f_cblk.slice_pts_ms = pts_ms;
501 | }
502 |
503 | f_cblk.slice_count++;
504 | }
505 |
506 | // Interpret packet.
507 | m2ts_data_interpret(desc, &pes_payload_size, &cc_start, &cc_end);
508 |
509 | f_cblk.pes_payload_curr_len += pes_payload_size;
510 |
511 | if(f_cblk.slice_pkt_count == 0)
512 | {
513 | // If first packet, just cache the last CC.
514 | f_cblk.last_cc = cc_end;
515 | }
516 | else
517 | {
518 | // If not first packet, check for continuity.
519 | if(((f_cblk.last_cc + 1) & 0x0F) == cc_start)
520 | {
521 | // Passes continuity test.
522 |
523 | f_cblk.last_cc = cc_end;
524 | }
525 | else
526 | {
527 | // Fails continuity test.
528 |
529 | printf("(video_decoder): last rtp seq num = %d\n", f_cblk.last_seq_num);
530 | printf("(video_decoder): curr rtp seq num = %d\n", ntohs(rtp_hdr->sequence_num));
531 |
532 | printf("(video_decoder): Packet loss detected! last_cc = %u, start_cc = %d\n",
533 | f_cblk.last_cc, cc_start);
534 |
535 | slice_drop();
536 |
537 | f_cblk.look_for_new_slice = 1;
538 |
539 | f_cblk.slice_pkt_count = 0;
540 |
541 | goto cleanup;
542 | }
543 | }
544 |
545 | slice_pkt_add(desc);
546 |
547 | // sx_pipe_put(SX_VRDMA_SLICE, desc);
548 |
549 | f_cblk.slice_pkt_count++;
550 |
551 | // printf("(video_decoder): ### 4, slice_pkt_count = %d, curr len = %d, total len = %d\n",
552 | // f_cblk.slice_pkt_count,
553 | // f_cblk.pes_payload_curr_len,
554 | // f_cblk.pes_payload_len);
555 |
556 | cleanup:
557 |
558 | f_cblk.last_seq_num = ntohs(rtp_hdr->sequence_num);
559 |
560 | } while (1);
561 |
562 | usleep(8*1000);
563 | }
564 | }
565 |
566 |
567 | // --------------------------------------------------------
568 | // common_resource_init
569 | // Initialize common resources
570 | //
571 | // Description:
572 | // This function initializes the common resources.
573 | //
574 | static void resources_init(
575 | void
576 | )
577 | {
578 | f_cblk.look_for_new_slice = 1;
579 | }
580 |
581 |
582 | // --------------------------------------------------------
583 | // decoder_thread_create
584 | // Creates decoder thread
585 | //
586 | // Description:
587 | // This function creates decoder thread.
588 | //
589 | static void decoder_thread_create(
590 | void
591 | )
592 | {
593 | sx_thread_create(&f_cblk.decoder_thread, &video_decoder_thread, NULL, VIDEO_DECODER_THREAD_PRIORITY);
594 | }
595 |
596 |
597 | // ========================================================
598 | // Public Functions
599 | // ========================================================
600 |
601 | void sx_mgmt_video_decoder_init(
602 | void
603 | )
604 | {
605 | // Initialize common resources.
606 | resources_init();
607 | }
608 |
609 |
610 | // --------------------------------------------------------
611 | // decoder_open
612 | // Opens decoder
613 | //
614 | void sx_mgmt_video_decoder_open(
615 | void
616 | )
617 | {
618 | // Initialize decoder thread.
619 | decoder_thread_create();
620 | }
621 |
622 |
623 | void sx_mgmt_video_decoder_close(
624 | void
625 | )
626 | {
627 | }
628 |
--------------------------------------------------------------------------------
/mgmt_video_scheduler/inc/sx_mgmt_video_scheduler.h:
--------------------------------------------------------------------------------
1 | #if !defined(SX_MGMT_VIDEO_DECODER_H)
2 | #define SX_MGMT_VIDEO_DECODER_H
3 |
4 | extern void sx_mgmt_video_decoder_init(
5 | void
6 | );
7 |
8 | extern void sx_mgmt_video_decoder_open(
9 | void
10 | );
11 |
12 | extern void sx_mgmt_video_decoder_close(
13 | void
14 | );
15 |
16 | #endif
17 |
18 |
--------------------------------------------------------------------------------
/mgmt_video_scheduler/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/mgmt_video_scheduler/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common desc pipe video_sink
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/mgmt_video_scheduler/src/sx_mgmt_video_scheduler.c:
--------------------------------------------------------------------------------
1 | // ========================================================
2 | // Includes
3 | // ========================================================
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "sx_system.h"
16 | #include "sx_pkt.h"
17 | #include "sx_desc.h"
18 | #include "sx_pipe.h"
19 | #include "sx_thread_priority.h"
20 | #include "sx_video_sink.h"
21 |
22 | // ========================================================
23 | // Constants
24 | // ========================================================
25 |
26 | // ========================================================
27 | // Private Types
28 | // ========================================================
29 |
30 | // Decoder control block
31 | typedef struct
32 | {
33 | pthread_t video_scheduler_thread;
34 | pthread_t slice_packing_thread;
35 | pthread_t pcr_update_thread;
36 | UINT64 curr_time;
37 | pthread_mutex_t lock;
38 |
39 | } sMGMT_VIDEO_SCHEDULER_CBLK;
40 |
41 |
42 | // ========================================================
43 | // Private Variables & Functions
44 | // ========================================================
45 |
46 | // Decoder control block.
47 | static sMGMT_VIDEO_SCHEDULER_CBLK f_cblk;
48 |
49 | static void video_scheduler_slice_dump(
50 | sSX_DESC *slice_head
51 | )
52 | {
53 | UINT8 *curr_ptr;
54 | UINT32 bytes_left;
55 | UINT32 afc;
56 | UINT32 pes_byte_count;
57 | UINT32 payload_size;
58 | UINT32 start_offset;
59 | UINT32 copy_index;
60 | UINT32 pid;
61 | sSX_DESC *curr_desc;
62 | sSX_DESC *head_desc;
63 |
64 |
65 | // Consistency check.
66 | assert(slice_head);
67 |
68 | // Get descriptor.
69 | sSX_DESC *hw_desc = sx_desc_get();
70 |
71 | // Set this as another chain.
72 | sSX_DESC *hw_desc_head = hw_desc;
73 |
74 | // Get a hw buffer.
75 | sDECODER_HW_BUFFER * hw_buf = sx_video_sink_buf_get();
76 | assert(hw_buf != NULL);
77 |
78 | // Set payload.
79 | hw_desc->data = (UINT8 *) hw_buf;
80 |
81 | // Get first descriptor.
82 | //
83 | // First descriptor holds the timestamp and will be skipped.
84 | curr_desc = slice_head;
85 |
86 | copy_index = 0;
87 | do
88 | {
89 | // Get next.
90 | curr_desc = curr_desc->next;
91 |
92 | // Get current.
93 | curr_ptr = curr_desc->data;
94 |
95 | // Get data left.
96 | bytes_left = curr_desc->data_len;
97 | assert(bytes_left > sizeof(sRTP_HDR));
98 |
99 | // Get RTP header.
100 | // sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr;
101 |
102 | // Get TS header.
103 | curr_ptr += sizeof(sRTP_HDR);
104 |
105 | // Get TS bytes left.
106 | bytes_left -= sizeof(sRTP_HDR);
107 | assert((bytes_left % sizeof(sMPEG2_TS)) == 0);
108 |
109 | pes_byte_count = 0;
110 | do
111 | {
112 | sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr;
113 | afc = AFC_GET(ts->hdr);
114 | pid = PID_GET(ts->hdr);
115 |
116 | if(pid == 0x1011)
117 | {
118 | UINT8 stuffing = 0;
119 | if(afc & 0x02)
120 | {
121 | stuffing = 1 + ts->payload.payload[0];
122 | }
123 |
124 | start_offset = stuffing;
125 |
126 | if(PUSI_GET(ts->hdr))
127 | {
128 | start_offset += 14;
129 | }
130 |
131 | payload_size = sizeof(sMPEG2_TS_PAYLOAD) - start_offset;
132 |
133 | if((copy_index + payload_size) > 81920)
134 | {
135 | // If the hw buffer is full, just submit the current buffer.
136 | hw_buf->buffer_len = copy_index;
137 |
138 | // Get a new descriptor.
139 | hw_desc->next = sx_desc_get();
140 |
141 | // Point to the new descriptor.
142 | hw_desc = hw_desc->next;
143 |
144 | // Get a new buffer.
145 | hw_buf = sx_video_sink_buf_get();
146 | assert(hw_buf != NULL);
147 |
148 | // Set new payload.
149 | hw_desc->data = (UINT8 *) hw_buf;
150 |
151 | // Reset index.
152 | copy_index = 0;
153 | }
154 |
155 | memcpy(&hw_buf->buffer[copy_index],
156 | &ts->payload.payload[start_offset],
157 | payload_size);
158 |
159 | copy_index += payload_size;
160 | }
161 |
162 | curr_ptr += sizeof(sMPEG2_TS);
163 | bytes_left -= sizeof(sMPEG2_TS);
164 |
165 | } while (bytes_left > 0);
166 |
167 | } while (curr_desc->next != NULL);
168 |
169 | // Set length.
170 | hw_buf->buffer_len = copy_index;
171 |
172 | // Free the existing slice, minus the head (timestamp).
173 | sx_desc_put(slice_head->next);
174 |
175 | // Set slice.
176 | slice_head->next = hw_desc_head;
177 |
178 | sx_pipe_put(SX_VRDMA_SLICE_READY, slice_head);
179 | }
180 |
181 |
182 | /**
183 | * Get current time on the sink.
184 | *
185 | * @return
186 | */
187 | static UINT64 sink_time_get(
188 | void
189 | )
190 | {
191 | struct timeval curr_time;
192 |
193 |
194 | // Get current time.
195 | gettimeofday(&curr_time, NULL);
196 |
197 | UINT64 temp = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
198 |
199 | return temp;
200 | }
201 |
202 |
203 | /**
204 | * Get estimated source time.
205 | *
206 | * @return
207 | */
208 | static UINT64 estimated_source_time_get(
209 | void
210 | )
211 | {
212 | UINT64 time;
213 |
214 |
215 | pthread_mutex_lock(&f_cblk.lock);
216 |
217 | time = f_cblk.curr_time;
218 |
219 | pthread_mutex_unlock(&f_cblk.lock);
220 |
221 | return time;
222 | }
223 |
224 |
225 | // --------------------------------------------------------
226 | // decoder_thread
227 | // Decoder thread
228 | //
229 | // Description:
230 | // This function defines the decoder thread.
231 | //
232 | void video_scheduler_thread(
233 | void * arg
234 | )
235 | {
236 | sSX_DESC *desc;
237 | UINT64 slice_present_time;
238 |
239 |
240 | desc = NULL;
241 | while(1)
242 | {
243 | while(1)
244 | {
245 | // -------------------
246 | // Get slice.
247 | // -------------------
248 |
249 | // Get slice.
250 | if(desc == NULL)
251 | {
252 | desc = sx_pipe_get(SX_VRDMA_SLICE_READY);
253 | if(desc == NULL)
254 | {
255 | goto next_iter;
256 | }
257 |
258 | sSLICE_HDR *hdr = (sSLICE_HDR *) desc->data;
259 |
260 | // Get PTS.
261 | slice_present_time = ((sSLICE_HDR *) desc->data)->timestamp;
262 | }
263 |
264 | UINT64 estimated_source_time = estimated_source_time_get();
265 | UINT8 present = (estimated_source_time > slice_present_time) ? 1 : 0;
266 |
267 | if(!present)
268 | {
269 | goto next_iter;
270 | }
271 |
272 | // -------------------
273 | // Present slice.
274 | // -------------------
275 |
276 | sSX_DESC *curr = desc->next;
277 | sSX_DESC *next;
278 | do
279 | {
280 | sx_video_sink_buf_set((sDECODER_HW_BUFFER *) curr->data);
281 |
282 | next = curr->next;
283 |
284 | free(curr);
285 |
286 | curr = next;
287 |
288 | } while (curr != NULL);
289 |
290 | free(desc->data);
291 | free(desc);
292 |
293 | // Set descriptor pointer to NULL.
294 | desc = NULL;
295 | }
296 |
297 | next_iter:
298 |
299 | usleep(1*1000);
300 | }
301 | }
302 |
303 |
304 | /**
305 | * Slice packing thread.
306 | *
307 | * @param arg
308 | */
309 | void slice_packing_thread(
310 | void * arg
311 | )
312 | {
313 | sSX_DESC *desc;
314 |
315 |
316 | desc = NULL;
317 | while(1)
318 | {
319 | UINT32 len = sx_pipe_len_get(SX_VRDMA_SLICE_READY);
320 | if(len >= 10)
321 | {
322 | // More than enough. Try again next iteration.
323 | goto next_iter;
324 | }
325 |
326 | UINT32 slices_to_dump = 10 - len;
327 | do
328 | {
329 | desc = sx_pipe_get(SX_VRDMA_SLICE);
330 | if(desc == NULL)
331 | {
332 | goto next_iter;
333 | }
334 |
335 | // Dump slice.
336 | video_scheduler_slice_dump(desc);
337 |
338 | slices_to_dump--;
339 |
340 | } while (slices_to_dump > 0);
341 |
342 | next_iter:
343 |
344 | usleep(2*1000);
345 | }
346 | }
347 |
348 |
349 | /**
350 | * Updates program clock reference time.
351 | *
352 | * @param arg
353 | */
354 | void pcr_update_thread(
355 | void * arg
356 | )
357 | {
358 | sSX_DESC *desc;
359 | UINT64 pcr_time;
360 | UINT64 pcr_received_time;
361 | UINT64 curr_time;
362 |
363 |
364 | while(1)
365 | {
366 | desc = sx_pipe_get(SX_VRDMA_PCR);
367 | if(desc == NULL)
368 | {
369 | goto cleanup;
370 | }
371 |
372 | sSLICE_HDR *hdr = (sSLICE_HDR *) desc->data;
373 |
374 | // Update PCR time.
375 | pcr_time = hdr->timestamp;
376 |
377 | // Free descriptor.
378 | sx_desc_put(desc);
379 |
380 | // Cache received time.
381 | pcr_received_time = sink_time_get();
382 |
383 | cleanup:
384 |
385 | // Get current time.
386 | curr_time = sink_time_get();
387 |
388 | pthread_mutex_lock(&f_cblk.lock);
389 |
390 | f_cblk.curr_time = pcr_time + (curr_time - pcr_received_time) - SX_SYSTEM_AUDIO_SOURCE_DELAY_MS - SX_SYSTEM_DELAY_MS;
391 |
392 | pthread_mutex_unlock(&f_cblk.lock);
393 |
394 | usleep(2*1000);
395 | }
396 | }
397 |
398 |
399 | // --------------------------------------------------------
400 | // common_resource_init
401 | // Initialize common resources
402 | //
403 | // Description:
404 | // This function initializes the common resources.
405 | //
406 | static void resources_init(
407 | void
408 | )
409 | {
410 | // Initialize decoder hardware.
411 | sx_video_sink_init();
412 |
413 | pthread_mutex_init(&f_cblk.lock, NULL);
414 | }
415 |
416 |
417 | // --------------------------------------------------------
418 | // decoder_thread_create
419 | // Creates decoder thread
420 | //
421 | // Description:
422 | // This function creates decoder thread.
423 | //
424 | static void video_scheduler_thread_create(
425 | void
426 | )
427 | {
428 | sx_thread_create(&f_cblk.video_scheduler_thread,
429 | &video_scheduler_thread,
430 | NULL,
431 | VIDEO_SCHEDULER_THREAD_PRIORITY);
432 |
433 | sx_thread_create(&f_cblk.slice_packing_thread,
434 | &slice_packing_thread,
435 | NULL,
436 | VIDEO_SCHEDULER_THREAD_PRIORITY);
437 |
438 | sx_thread_create(&f_cblk.pcr_update_thread,
439 | &pcr_update_thread,
440 | NULL,
441 | VIDEO_SCHEDULER_THREAD_PRIORITY);
442 | }
443 |
444 |
445 | // ========================================================
446 | // Public Functions
447 | // ========================================================
448 |
449 | void sx_mgmt_video_scheduler_init(
450 | void
451 | )
452 | {
453 | // Initialize common resources.
454 | resources_init();
455 | }
456 |
457 |
458 | // --------------------------------------------------------
459 | // decoder_open
460 | // Opens decoder
461 | //
462 | void sx_mgmt_video_scheduler_open(
463 | void
464 | )
465 | {
466 | // Initialize decoder thread.
467 | video_scheduler_thread_create();
468 | }
469 |
470 |
471 | void sx_mgmt_video_scheduler_close(
472 | void
473 | )
474 | {
475 | }
476 |
--------------------------------------------------------------------------------
/pipe/inc/sx_pipe.h:
--------------------------------------------------------------------------------
1 | #if !defined(_SX_VRDMA_H_)
2 | #define _SX_VRDMA_H_
3 |
4 | #define SX_VRDMA_PKT_QUEUE 0
5 | #define SX_VRDMA_VIDEO_PKT_QUEUE 1
6 | #define SX_VRDMA_SLICE 2
7 | #define SX_VRDMA_SLICE_READY 3
8 | #define SX_VRDMA_PCR 4
9 | #define SX_VRDMA_LPCM 5
10 | #define SX_VRDMA_LPCM_SLICE 6
11 | #define SX_VRDMA_MAX 7
12 |
13 | extern void sx_pipe_init(
14 | void
15 | );
16 |
17 | extern void sx_pipe_put(
18 | UINT32 index,
19 | void *data
20 | );
21 |
22 | extern void * sx_pipe_get(
23 | UINT32 index
24 | );
25 |
26 | extern unsigned int sx_pipe_len_get(
27 | UINT32 index
28 | );
29 |
30 | #endif // _SX_VRDMA_H_
31 |
--------------------------------------------------------------------------------
/pipe/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/pipe/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/pipe/src/sx_pipe.c:
--------------------------------------------------------------------------------
1 | #include "sx_types.h"
2 | #include "sx_queue.h"
3 | #include "sx_pipe.h"
4 |
5 |
6 | typedef struct
7 | {
8 | SX_QUEUE queue[SX_VRDMA_MAX];
9 |
10 | } sVRDMA_CBLK;
11 |
12 |
13 | static sVRDMA_CBLK f_cblk;
14 |
15 |
16 | void sx_pipe_init(
17 | void
18 | )
19 | {
20 | UINT32 i;
21 |
22 |
23 | for(i = 0; i < SX_VRDMA_MAX; i++)
24 | {
25 | // Create queue.
26 | f_cblk.queue[i] = sx_queue_create();
27 | }
28 | }
29 |
30 |
31 | void sx_pipe_put(
32 | UINT32 index,
33 | void *data
34 | )
35 | {
36 | sx_queue_push(f_cblk.queue[index], data);
37 | }
38 |
39 |
40 | void * sx_pipe_get(
41 | UINT32 index
42 | )
43 | {
44 | return sx_queue_pull(f_cblk.queue[index]);
45 | }
46 |
47 |
48 | unsigned int sx_pipe_len_get(
49 | UINT32 index
50 | )
51 | {
52 | return sx_queue_len_get(f_cblk.queue[index]);
53 | }
54 |
--------------------------------------------------------------------------------
/release/release.py:
--------------------------------------------------------------------------------
1 | # Piracast project release script.
2 | # This script generates the release package for release.
3 |
4 | import os
5 | import shutil
6 | import subprocess
7 |
8 | # Change to target directory.
9 | os.chdir("../target")
10 |
11 | # Compile application.
12 | cmd_make_app = 'make clobber app'
13 | os.system(cmd_make_app)
14 |
15 | # Change to application directory.
16 | os.chdir("../application")
17 |
18 | # Freeze main.
19 | print 'Freezing python application...'
20 | cmd_freeze_main = 'cxfreeze main.py'
21 | os.system(cmd_freeze_main)
22 |
23 | # Go back to release directory.
24 | os.chdir("../release")
25 |
26 | print 'Creating directories...'
27 | cmd_mkdir_piracast = 'mkdir piracast'
28 | os.system(cmd_mkdir_piracast)
29 |
30 | os.chdir("./piracast")
31 | cmd_mkdir_application = 'mkdir application'
32 | os.system(cmd_mkdir_application)
33 |
34 | cmd_mkdir_installer = 'mkdir installer'
35 | os.system(cmd_mkdir_installer)
36 |
37 | # Go back to release directory.
38 | os.chdir("../")
39 |
40 | # Copy application files.
41 | paths = ['../application/hostapd',
42 | '../application/hostapd_cli',
43 | '../application/p2p_hostapd.conf',
44 | '../application/wpa_0_8.conf',
45 | '../application/wpa_cli',
46 | '../application/wpa_supplicant',
47 | '../application/app',
48 | '../application/dist/main']
49 |
50 | for path in paths :
51 | shutil.copy(path, 'piracast/application')
52 |
53 | # # Enable executables.
54 | # executables = ['piracast/application/hostapd',
55 | # 'piracast/application/hostapd_cli',
56 | # 'piracast/application/wpa_cli',
57 | # 'piracast/application/wpa_supplicant',
58 | # 'piracast/application/app']
59 | #
60 | # for executable in executables :
61 | # enable_add_permission_cmd = 'chmod 777 ' + executable
62 | # os.system(enable_add_permission_cmd)
63 |
64 | # Copy installer files.
65 | installs = ['../environment/8188eu.ko',
66 | '../environment/isc-dhcp-server',
67 | '../environment/dhcpd.conf',
68 | '../environment/interfaces',
69 | '../environment/setup.py']
70 |
71 | for install in installs :
72 | shutil.copy(install, 'piracast/installer')
73 |
74 | # Copy instruction files.
75 | instructions = [
76 | '../environment/README'
77 | ]
78 |
79 | for instruction in instructions :
80 | shutil.copy(instruction, 'piracast')
81 |
82 | print 'Create tar package...'
83 | cmd_tar_piracast = 'tar -zcvf piracast.tar.gz piracast'
84 | os.system(cmd_tar_piracast)
85 |
86 | print 'Release package ready!'
87 |
--------------------------------------------------------------------------------
/scripts/core_channel.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8 -*-
2 |
3 | # This file is part of Piracast.
4 | #
5 | # Piracast is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Piracast is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Piracast. If not, see .
17 |
18 | import socket
19 | import sys
20 |
21 | def end():
22 |
23 | # Create a UDS socket
24 | sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
25 |
26 | # Connect the socket to the port where the server is listening
27 | server_address = './demo_socket'
28 | print >>sys.stderr, 'connecting to %s' % server_address
29 | try:
30 | sock.connect(server_address)
31 | except socket.error, msg:
32 | print >>sys.stderr, msg
33 | return
34 |
35 | message = 'This is the message. It will be repeated.'
36 | print >>sys.stderr, 'sending "%s"' % message
37 | sock.sendall(message)
38 |
39 | sock.close()
40 |
41 |
--------------------------------------------------------------------------------
/scripts/env.txt:
--------------------------------------------------------------------------------
1 | displayWidth 1680
2 | displayHeight 1050
3 | sessionWidth 1280
4 | sessionWidth 720
5 |
6 |
--------------------------------------------------------------------------------
/scripts/graph_generate.txt:
--------------------------------------------------------------------------------
1 | gprof app gmon.out | python gprof2dot.py | dot -Tjpg -Gdpi=300 -o output.jpg
2 |
--------------------------------------------------------------------------------
/scripts/hostapd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemonkeyricky/piracast/04a0d2b6bec6c408ef41d872034333903f6fabe5/scripts/hostapd
--------------------------------------------------------------------------------
/scripts/hostapd_cli:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemonkeyricky/piracast/04a0d2b6bec6c408ef41d872034333903f6fabe5/scripts/hostapd_cli
--------------------------------------------------------------------------------
/scripts/p2p_hostapd.conf:
--------------------------------------------------------------------------------
1 | ##### hostapd configuration file ##############################################
2 |
3 | interface=wlan0
4 | ctrl_interface=/var/run/hostapd
5 | ssid=DIRECT-RT
6 | channel=6
7 | wpa=2
8 | wpa_passphrase=12345678
9 |
10 |
11 |
12 | ##### Wi-Fi Protected Setup (WPS) #############################################
13 |
14 | eap_server=1
15 |
16 | # WPS state
17 | # 0 = WPS disabled (default)
18 | # 1 = WPS enabled, not configured
19 | # 2 = WPS enabled, configured
20 | wps_state=2
21 |
22 | uuid=12345678-9abc-def0-1234-56789abcdef0
23 |
24 | # Device Name
25 | # User-friendly description of device; up to 32 octets encoded in UTF-8
26 | device_name=RTL8192CU
27 |
28 | # Manufacturer
29 | # The manufacturer of the device (up to 64 ASCII characters)
30 | manufacturer=Realtek
31 |
32 | # Model Name
33 | # Model of the device (up to 32 ASCII characters)
34 | model_name=RTW_SOFTAP
35 |
36 | # Model Number
37 | # Additional device description (up to 32 ASCII characters)
38 | model_number=WLAN_CU
39 |
40 | # Serial Number
41 | # Serial number of the device (up to 32 characters)
42 | serial_number=12345
43 |
44 | # Primary Device Type
45 | # Used format: --
46 | # categ = Category as an integer value
47 | # OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for
48 | # default WPS OUI
49 | # subcateg = OUI-specific Sub Category as an integer value
50 | # Examples:
51 | # 1-0050F204-1 (Computer / PC)
52 | # 1-0050F204-2 (Computer / Server)
53 | # 5-0050F204-1 (Storage / NAS)
54 | # 6-0050F204-1 (Network Infrastructure / AP)
55 | device_type=6-0050F204-1
56 |
57 | # OS Version
58 | # 4-octet operating system version number (hex string)
59 | os_version=01020300
60 |
61 | # Config Methods
62 | # List of the supported configuration methods
63 | config_methods=label display push_button keypad
64 |
65 |
66 | ##### default configuration #######################################
67 |
68 | driver=rtl871xdrv
69 | beacon_int=100
70 | hw_mode=g
71 | ieee80211n=1
72 | wme_enabled=1
73 | ht_capab=[SHORT-GI-20][SHORT-GI-40][HT40+]
74 | wpa_key_mgmt=WPA-PSK
75 | wpa_pairwise=CCMP
76 | max_num_sta=8
77 | wpa_group_rekey=86400
78 | supported_rates=60 90 120 180 240 360 480 540
79 | basic_rates=60 120 240
80 |
--------------------------------------------------------------------------------
/scripts/piracast.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: UTF-8 -*-
3 |
4 | # This file is part of Piracast.
5 | #
6 | # Piracast is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # Piracast is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with Piracast. If not, see .
18 |
19 | import os
20 | import re
21 | import time
22 |
23 | import wfd
24 | import core_channel
25 | import sink
26 |
27 | from util import get_stdout
28 |
29 | cmd_wlan0_up = 'ifup wlan0'
30 | cmd_inc_rmem_default = 'sysctl -w net.core.rmem_default=1000000'
31 | #cmd_launch_core_app = 'nice -n -20 ./core 1>/dev/null &'
32 | cmd_launch_core_app = 'nice -n -20 ./core'
33 | #cmd_kill_core_app = 'python core_terminate.py'
34 | cmd_kill_core_app = 'killall core'
35 | cmd_dhcp_start = 'service isc-dhcp-server start'
36 | cmd_dhcp_stop = 'service isc-dhcp-server stop'
37 |
38 | lease_file = '/var/lib/dhcp/dhcpd.leases'
39 |
40 | def lease_file_timestamp_get():
41 | return get_stdout('ls -l "%s"' % lease_file)
42 |
43 | # get the leased IP address
44 | def leased_ip_get():
45 | contents = open(lease_file).read()
46 | ip_list = re.findall(r'lease (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', contents)
47 |
48 | # return the most recently leased IP address
49 | return ip_list[-1]
50 |
51 | print 'Bring up wlan0 just in case...'
52 | get_stdout(cmd_wlan0_up)
53 |
54 | print 'Increase rmem_default...'
55 | get_stdout(cmd_inc_rmem_default)
56 |
57 | # Don't kill running application as
58 | # it is started explicitly
59 | #print 'Kill running application...'
60 | #core_channel.end()
61 | #print get_stdout(cmd_kill_core_app)
62 |
63 | while 1:
64 |
65 | # Don't launch application, because it stuck
66 | # the execution
67 | # get_stdout(cmd_launch_core_app)
68 |
69 | # Start DHCP
70 | print get_stdout(cmd_dhcp_start)
71 |
72 | # Get previous timestamp
73 | prev_ts = lease_file_timestamp_get()
74 |
75 | # Wait for connection
76 | wfd.wfd_connection_wait()
77 |
78 | # Wait until lease file is updated
79 | while 1:
80 |
81 | curr_ts = lease_file_timestamp_get()
82 |
83 | if curr_ts != prev_ts:
84 |
85 | print 'Source has requested IP!'
86 |
87 | # wait for network to be properly configured
88 | time.sleep(2)
89 |
90 | break
91 |
92 | print 'lease table has not been updated, wait for a second...'
93 |
94 | time.sleep(1)
95 |
96 | # Get source IP
97 | ip = leased_ip_get()
98 |
99 | print 'leased IP: ', ip
100 |
101 | # Connect to source
102 | sink.source_connect(ip)
103 |
104 | # Stop DHCPd
105 | output = get_stdout(cmd_dhcp_stop)
106 | #print output
107 |
108 | # Kill app
109 | #core_channel.end()
110 | output = get_stdout(cmd_kill_core_app)
111 | print output
112 |
113 |
--------------------------------------------------------------------------------
/scripts/sink.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8 -*-
2 |
3 | # This file is part of Piracast.
4 | #
5 | # Piracast is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Piracast is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Piracast. If not, see .
17 |
18 | import re
19 | import socket
20 |
21 | m1_options_rsp = 'RTSP/1.0 200 OK\r\n' \
22 | 'Date: Sun, 11 Aug 2013 04:41:40 +000\r\n' \
23 | 'Server: stagefright/1.2 (Linux;Android 4.3)\r\n' \
24 | 'CSeq: 1\r\n' \
25 | 'Public: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\r\n' \
26 | '\r\n'
27 |
28 | m2_req = 'OPTIONS * RTSP/1.0\r\n' \
29 | 'Date: Sun, 11 Aug 2013 04:41:40 +000\r\n' \
30 | 'Server: stagefright/1.2 (Linux;Android 4.3)\r\n' \
31 | 'CSeq: 2\r\n' \
32 | 'Require: org.wfa.wfd1.0\r\n' \
33 | '\r\n'
34 |
35 | m3_body = 'wfd_video_formats: 39 00 02 02 0001FFFF 3FFFFFFF 00000000 00 0000 0000 00 none none\r\n' \
36 | 'wfd_audio_codecs: LPCM 00000002 00\r\n' \
37 | 'wfd_client_rtp_ports: RTP/AVP/UDP;unicast 50000 0 mode=play\r\n'
38 |
39 | m3_rsp = 'RTSP/1.0 200 OK\r\n' \
40 | 'Date: Sun, 11 Aug 2013 04:41:40 +000\r\n' \
41 | 'Server: stagefright/1.2 (Linux;Android 4.3)\r\n' \
42 | 'CSeq: 2\r\n' \
43 | 'Content-Type: text/parameters\r\n' \
44 | 'Content-Length: ' + str(len(m3_body)) + '\r\n' \
45 | '\r\n' + m3_body
46 |
47 | m4_rsp = 'RTSP/1.0 200 OK\r\n' \
48 | 'Date: Sun, 11 Aug 2013 04:41:40 +000\r\n' \
49 | 'Server: stagefright/1.2 (Linux;Android 4.3)\r\n' \
50 | 'CSeq: 3\r\n' \
51 | '\r\n'
52 |
53 | m5_rsp = 'RTSP/1.0 200 OK\r\n' \
54 | 'Date: Sun, 11 Aug 2013 04:41:40 +000\r\n' \
55 | 'Server: stagefright/1.2 (Linux;Android 4.3)\r\n' \
56 | 'CSeq: 4\r\n' \
57 | '\r\n'
58 |
59 | m6_req = 'SETUP rtsp://{}/wfd1.0/streamid=0 RTSP/1.0\r\n' \
60 | 'Date: Sun, 11 Aug 2013 04:41:40 +000\r\n' \
61 | 'Server: stagefright/1.2 (Linux;Android 4.3)\r\n' \
62 | 'CSeq: 4\r\n' \
63 | 'Transport: RTP/AVP/UDP;unicast;client_port=50000-50001\r\n' \
64 | '\r\n'
65 |
66 | m7_req = 'PLAY rtsp://{}/wfd1.0/streamid=0 RTSP/1.0\r\n' \
67 | 'Date: Sun, 11 Aug 2013 04:41:40 +000\r\n' \
68 | 'Server: stagefright/1.2 (Linux;Android 4.3)\r\n' \
69 | 'CSeq: 5\r\n' \
70 | 'Session: {}\r\n' \
71 | '\r\n'
72 |
73 | m16_rsp = 'RTSP/1.0 200 OK\r\n' \
74 | 'Date: Sun, 11 Aug 2013 04:41:40 +000\r\n' \
75 | 'Server: stagefright/1.2 (Linux;Android 4.3)\r\n' \
76 | 'CSeq: {}\r\n' \
77 | '\r\n'
78 |
79 | def source_connect(ip):
80 |
81 | # Create a socket object
82 | s = socket.socket()
83 |
84 | # Connect to port
85 | s.connect((ip, 7236))
86 |
87 | # Connect via wireless interface
88 | s.setsockopt(socket.SOL_SOCKET, 25, 'wlan0')
89 |
90 | # Wait to receive data
91 | data = s.recv(1024)
92 |
93 | print 'Received %s' % repr(data)
94 |
95 | # Send m1 response
96 | s.send(m1_options_rsp)
97 |
98 | # Send m2 request
99 | s.send(m2_req)
100 |
101 | # Receive m2 response
102 | m2_rsp = s.recv(1024)
103 |
104 | print 'M2 Resp: %s' % repr(m2_rsp)
105 |
106 | # Receive: M3 GET_PARAMETER Request
107 | m3_req = s.recv(1024)
108 |
109 | print 'M3 Req:\n%s\n' % repr(m3_req)
110 |
111 | print 'M3 Resp:\n%s\n' % repr(m3_rsp)
112 |
113 | # Send: M3 Response
114 | s.send(m3_rsp)
115 |
116 | # Receive: M4 RTSP SET_PARAMETER Request
117 | m4_req = s.recv(1024)
118 |
119 | print 'M4 Req:\n%s\n' % repr(m4_req)
120 |
121 | print 'M4 Resp:\n%s\n' % repr(m4_rsp)
122 |
123 | # Send: M4 response
124 | s.send(m4_rsp)
125 |
126 | # Receive: M5 RTSP SET_PARAMETER Request (setup)
127 | m5_req = s.recv(1024)
128 |
129 | # Send: M5 Response
130 | s.send(m5_rsp)
131 |
132 | # Send: M6 RTSP SETUP
133 | s.send(m6_req.format(ip))
134 |
135 | # Receive: M6 RTSP SETUP response
136 | m6_rsp = s.recv(1024)
137 |
138 | print 'M6 Rsp: %s' % repr(m6_rsp)
139 |
140 | # TODO: extract session ID
141 | match = re.search(r'Session: (\d*)', m6_rsp)
142 |
143 | # Send: M6 Request
144 | s.send(m7_req.format(ip, match.group(1)))
145 |
146 | m7_rsp = s.recv(1024)
147 |
148 | print 'M7 Rsp: %s' % repr(m7_rsp)
149 |
150 | cseq = 5
151 |
152 | keepalives_sent = 0
153 |
154 | while 1:
155 | req = s.recv(1024)
156 |
157 | print 'req: %s' % req
158 |
159 | if req.__len__() == 0:
160 | print 'socket closed!'
161 | break
162 |
163 | if 'TEARDOWN' in req:
164 | print 'Teardown received!'
165 | break
166 |
167 | #if keepalives_sent == 120:
168 | # print 'demo time\'s up!'
169 | # break
170 |
171 | s.send(m16_rsp.format(cseq))
172 |
173 | print 'sent keepalive!'
174 |
175 | cseq += 1
176 |
177 | keepalives_sent += 1
178 |
179 | s.close()
180 |
--------------------------------------------------------------------------------
/scripts/util.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8 -*-
2 |
3 | # This file is part of Piracast.
4 | #
5 | # Piracast is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Piracast is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Piracast. If not, see .
17 |
18 | import subprocess
19 |
20 | def get_stdout(args):
21 | cmd = subprocess.Popen(args, shell=isinstance(args, basestring), stdout=subprocess.PIPE)
22 | (stdoutdata, stderrdata) = cmd.communicate()
23 | return stdoutdata
24 |
--------------------------------------------------------------------------------
/scripts/wfd.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8 -*-
2 |
3 | # This file is part of Piracast.
4 | #
5 | # Piracast is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Piracast is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Piracast. If not, see .
17 |
18 | import re
19 | import time
20 |
21 | from util import get_stdout
22 |
23 | cmd_killall_wpa_spplicant = 'killall wpa_supplicant'
24 | cmd_killall_hostapd = 'killall hostapd'
25 | cmd_iwlist_wlan0_scan = 'iwlist wlan0 scan'
26 |
27 | def peer_mac_get():
28 | output = get_stdout('iwpriv wlan0 p2p_get peer_ifa')
29 | match = re.search(r'MAC (.*)$', output)
30 | return match.group(1)
31 |
32 | def wpa_supplicant_start():
33 | print 'wpa_supplicant_start:'
34 | get_stdout(["./wpa_supplicant", "-i", "wlan0", "-c", "./wpa_0_8.conf", "-B"])
35 | time.sleep(1)
36 |
37 | def wps_auth():
38 | print 'wps_auth:'
39 | output = get_stdout(["./hostapd_cli", "wps_pbc", "any"])
40 | print output
41 | time.sleep(1)
42 |
43 | def wps_status_get():
44 | print 'wps_status_get:'
45 | output = get_stdout(["./wpa_cli", "status"])
46 | print output
47 |
48 | def p2p_wpsinfo():
49 | print 'p2p_wpsinfo:'
50 | get_stdout('iwpriv wlan0 p2p_set got_wpsinfo=3')
51 |
52 | def p2p_status_get():
53 | #print 'p2p_status_get:'
54 | output = get_stdout('iwpriv wlan0 p2p_get status')
55 | match = re.search(r'Status=(\d*)', output)
56 | return int(match.group(1))
57 |
58 | def p2p_set_nego(mac):
59 | print 'p2p_set_nego:'
60 | print 'mac: %s' % mac
61 | get_stdout('iwpriv wlan0 p2p_set nego=%s' % mac)
62 |
63 | # Enter negotiation loop
64 | while 1:
65 |
66 | # Wait for result
67 | time.sleep(0.5)
68 |
69 | # Poll status
70 | peer_status = p2p_status_get()
71 | print 'peer_status: %d' % peer_status
72 |
73 | # For Windows 8.1 support, we consider 19 as negotiation completed
74 | if peer_status in [10, 19]:
75 | print 'Negotiation suceeded!'
76 | break
77 |
78 | # Get role
79 | role = p2p_role_get()
80 | print 'Role: %s' % role
81 |
82 | # TODO: doesn't seem to return anything
83 | #p2p_opch_get()
84 |
85 | # Get peer interface address
86 | peer_mac_get()
87 |
88 | p2p_go_mode_set()
89 |
90 | # -----------------------
91 | # p2p_enable
92 | # Enable wifi direct
93 | # -----------------------
94 | def p2p_enable():
95 |
96 | # Enable p2p
97 | get_stdout('iwpriv wlan0 p2p_set enable=1')
98 |
99 | # Set intent
100 | get_stdout('iwpriv wlan0 p2p_set intent=15')
101 |
102 | # Set operation channel
103 | get_stdout('iwpriv wlan0 p2p_set op_ch=%d' % 11)
104 |
105 | # Sleep for 50ms
106 | time.sleep(0.05)
107 |
108 | # Set ssid
109 | get_stdout('iwpriv wlan0 p2p_set ssid=DIRECT-RT')
110 |
111 | # Set DN
112 | get_stdout('iwpriv wlan0 p2p_set setDN=Piracast')
113 |
114 | #print 'p2p_get role...'
115 | #get_stdout('iwpriv wlan0 p2p_get role')
116 |
117 | #print 'scan...'
118 | #get_stdout('iwlist wlan0 scan')
119 |
120 | # -----------------------
121 | # p2p_peer_devaddr_get
122 | # Gets peer device address
123 | # -----------------------
124 | def p2p_peer_devaddr_get():
125 | print 'p2p_peer_devaddr_get:'
126 | output = get_stdout(["iwpriv", "wlan0", "p2p_get", "peer_deva"])
127 | match = re.search(r'\n(.*)$', output)
128 | mac = ':'.join(re.findall('..', match.group(1)))
129 | #mac = match.group(1)[0] + match.group(1)[1] + ':' \
130 | # + match.group(1)[2] + match.group(1)[3] + ':' \
131 | # + match.group(1)[4] + match.group(1)[5] + ':' \
132 | # + match.group(1)[6] + match.group(1)[7] + ':' \
133 | # + match.group(1)[8] + match.group(1)[9] + ':' \
134 | # + match.group(1)[10] + match.group(1)[11]
135 |
136 | return mac
137 |
138 | # -----------------------
139 | # p2p_req_cm_get
140 | # Gets supported authentication type
141 | # -----------------------
142 | def p2p_req_cm_get():
143 | print 'p2p_req_cm_get:'
144 | print get_stdout('iwpriv wlan0 p2p_get req_cm')
145 |
146 | def p2p_role_get():
147 | print 'p2p_role_get:'
148 | output = get_stdout('iwpriv wlan0 p2p_get role')
149 | match = re.search(r'Role=(\d*)', output)
150 | role = int(match.group(1))
151 | return role
152 |
153 | def p2p_opch_get():
154 | print 'p2p_opch_get:'
155 | print '---------------------------'
156 | output = get_stdout('iwpriv wlan0 p2p_get op_ch')
157 | print output
158 | print '---------------------------'
159 | #match = re.search(r'Role=(\d*)', output)
160 | #role = int(match.group(1))
161 | #return role
162 |
163 | def p2p_go_mode_set():
164 |
165 | # Start hostAPd and wait for it to daemonize; ignore stdout
166 | get_stdout(["./hostapd", "-B", "p2p_hostapd.conf"])
167 |
168 | # Wait for initialization
169 | time.sleep(1)
170 |
171 | do_wps()
172 |
173 | # Wait for host apd interval
174 | time.sleep(1)
175 |
176 | while 1:
177 | status = read_all_sta()
178 |
179 | if status:
180 | print 'Wireless display negotiation completed!'
181 | break
182 |
183 | time.sleep(1)
184 |
185 | def do_wps():
186 |
187 | while 1:
188 | print 'do_wps:'
189 | output = get_stdout(["./hostapd_cli", "wps_pbc", "any"])
190 |
191 | print output
192 |
193 | if 'OK' in output:
194 | print 'wps passed!'
195 | return
196 |
197 | time.sleep(1)
198 |
199 | def read_all_sta():
200 | print 'read_all_sta:'
201 | output = get_stdout(["./hostapd_cli", "all_sta"])
202 | return ('dot11RSNAStatsSTAAddress' in output)
203 |
204 | def p2p_disable():
205 | get_stdout('iwpriv wlan0 p2p_set enable=0')
206 |
207 | def p2p_peer_scan():
208 | count = 0
209 |
210 | while 1:
211 | output = get_stdout(cmd_iwlist_wlan0_scan)
212 |
213 | print output
214 |
215 | if 'No scan results' not in output:
216 | return True
217 |
218 | if count > 3:
219 | return False
220 |
221 | count += 1
222 |
223 | def wfd_connection_wait():
224 | get_stdout(cmd_killall_wpa_spplicant)
225 | get_stdout(cmd_killall_hostapd)
226 |
227 | # Disable p2p
228 | p2p_disable()
229 |
230 | time.sleep(0.5)
231 |
232 | # Enable p2p
233 | p2p_enable()
234 |
235 | #p2p_peer_scan()
236 |
237 | print 'Waiting for incoming connection...'
238 |
239 | while 1:
240 |
241 | peer_status = p2p_status_get()
242 |
243 | print 'peer_status: %d' % peer_status
244 |
245 | if peer_status == 0:
246 | print 'p2p disabled! Re-enable p2p...'
247 | p2p_enable()
248 |
249 | #if peer_status == 11:
250 | # print 'p2p request received! Scan for peer ...'
251 | # p2p_peer_scan()
252 |
253 | # status 8 is the original Discovery Request
254 | # status 22 needs to be handled this way, or Nexus 4 4.4 won't always work
255 | # status 19 was added to try to implement windows 8.1 support
256 | if peer_status in [8, 19, 22]:
257 | # Discovery request or gonego fail
258 | print 'Discovery request received!'
259 | peer_found = p2p_peer_scan()
260 |
261 | if peer_found:
262 | break
263 |
264 | p2p_disable()
265 |
266 | time.sleep(1)
267 |
268 | print 'Getting peer device address...'
269 |
270 | # Get peer device address
271 | mac = p2p_peer_devaddr_get()
272 | print 'peer_devaddr: %s' % mac
273 |
274 | # Notify received wps info
275 | p2p_wpsinfo()
276 |
277 | print 'Getting peer authentication type...'
278 |
279 | # Get request configuration
280 | p2p_req_cm_get()
281 |
282 | print 'Confirming peer authentication...'
283 |
284 | #print 'Getting status...'
285 |
286 | # Get status
287 | #peer_status = p2p_status_get()
288 | #print 'peer_status: ', peer_status
289 |
290 | # Set negotiation
291 | p2p_set_nego(mac)
292 |
--------------------------------------------------------------------------------
/scripts/wpa_0_8.conf:
--------------------------------------------------------------------------------
1 | ctrl_interface=/var/run/wpa_supplicant
2 | update_config=1
3 |
4 | # Wi-Fi Protected Setup (WPS) parameters
5 |
6 | # Device Name
7 | # User-friendly description of device; up to 32 octets encoded in UTF-8
8 | device_name=RTL8192CU
9 |
10 | # Manufacturer
11 | # The manufacturer of the device (up to 64 ASCII characters)
12 | manufacturer=Realtek
13 |
14 | # Model Name
15 | # Model of the device (up to 32 ASCII characters)
16 | model_name=RTW_STA
17 |
18 | # Model Number
19 | # Additional device description (up to 32 ASCII characters)
20 | model_number=WLAN_CU
21 |
22 | # Serial Number
23 | # Serial number of the device (up to 32 characters)
24 | serial_number=12345
25 |
26 | # Primary Device Type
27 | # Used format: --
28 | # categ = Category as an integer value
29 | # OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for
30 | # default WPS OUI
31 | # subcateg = OUI-specific Sub Category as an integer value
32 | # Examples:
33 | # 1-0050F204-1 (Computer / PC)
34 | # 1-0050F204-2 (Computer / Server)
35 | # 5-0050F204-1 (Storage / NAS)
36 | # 6-0050F204-1 (Network Infrastructure / AP)
37 | device_type=1-0050F204-1
38 |
39 | # OS Version
40 | # 4-octet operating system version number (hex string)
41 | os_version=01020300
42 |
43 | # Config Methods
44 | # List of the supported configuration methods
45 | # Available methods: usba ethernet label display ext_nfc_token int_nfc_token
46 | # nfc_interface push_button keypad virtual_display physical_display
47 | # virtual_push_button physical_push_button
48 | # For WSC 1.0:
49 | #config_methods=display push_button keypad
50 | # For WSC 2.0:
51 | config_methods=virtual_display virtual_push_button keypad
52 |
--------------------------------------------------------------------------------
/scripts/wpa_cli:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemonkeyricky/piracast/04a0d2b6bec6c408ef41d872034333903f6fabe5/scripts/wpa_cli
--------------------------------------------------------------------------------
/scripts/wpa_supplicant:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codemonkeyricky/piracast/04a0d2b6bec6c408ef41d872034333903f6fabe5/scripts/wpa_supplicant
--------------------------------------------------------------------------------
/target/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/target/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := mgmt_sys
2 |
3 | DEP_OBJ := common desc pipe mgmt_sys mgmt_data mgmt_m2ts_decoder
4 | DEP_OBJ += mgmt_audio_decoder mgmt_video_decoder mgmt_video_scheduler
5 | DEP_OBJ += video_sink target audio_sink mgmt_audio_scheduler mgmt_env
6 | DEP_OBJ += mgmt_ctl
7 |
--------------------------------------------------------------------------------
/target/src/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "sx_mgmt_sys.h"
4 |
5 |
6 | int main(
7 | int argc,
8 | char *argv[]
9 | )
10 | {
11 | // Initialized system.
12 | mgmt_sys_init();
13 |
14 | // Open system.
15 | mgmt_sys_open();
16 | }
17 |
--------------------------------------------------------------------------------
/video_sink/inc/sx_video_sink.h:
--------------------------------------------------------------------------------
1 | #if !defined(DECODER_HW_H)
2 | #define DECODER_HW_H
3 |
4 | #define DECODER_HW_BUFFER_SIZE_MAX (16*1024)
5 |
6 | // This is an overlay of OMX_BUFFERHEADERTYPE to reduce dependency.
7 | //
8 | typedef struct
9 | {
10 | unsigned int reserve1; // nSize
11 | unsigned int reserved2; // nVersion
12 | unsigned char *buffer; // pBuffer
13 | unsigned int reserved3; // nAllocLen
14 | unsigned int buffer_len; // nFilledLen
15 | unsigned int reserved4; // nOffset
16 | unsigned int reserved5; // pAppPrivate
17 | unsigned int reserved6; // pPlatformPrivate;
18 | unsigned int reserved7; // pInputPortPrivate;
19 | unsigned int reserved8; // pOutputPortPrivate
20 | unsigned int reserved9; // hMarkTargetComponent
21 | unsigned int reserved10; // pMarkData
22 | unsigned int reserved11; // nTickCount
23 | unsigned int reserved12; // nTimeStamp
24 | unsigned int reserved13; // nFlags
25 | unsigned int reserved14; // nOutputPortIndex
26 | unsigned int reserved15; // nInputPortIndex
27 |
28 | } sDECODER_HW_BUFFER;
29 |
30 |
31 | extern void sx_video_sink_init(
32 | void
33 | );
34 |
35 |
36 | extern sDECODER_HW_BUFFER * sx_video_sink_buf_get(
37 | void
38 | );
39 |
40 |
41 | extern void sx_video_sink_buf_set(
42 | sDECODER_HW_BUFFER *decoder_hw_buf
43 | );
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/video_sink/makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(PLATFORM_ROOT),)
2 | PLATFORM_ROOT := ..
3 | export PLATFORM_ROOT
4 | endif
5 |
6 | include $(PLATFORM_ROOT)/common/make/makefile.std
7 |
--------------------------------------------------------------------------------
/video_sink/makefile_includes.make:
--------------------------------------------------------------------------------
1 | DEP_INC := common mgmt_env
2 |
3 | DEP_OBJ :=
4 |
--------------------------------------------------------------------------------
/video_sink/src/sx_video_sink.c:
--------------------------------------------------------------------------------
1 | // ========================================================
2 | // Includes
3 | // ========================================================
4 | #include
5 | #include
6 |
7 | #include "bcm_host.h"
8 | #include "ilclient.h"
9 |
10 | #include "sx_mgmt_env.h"
11 | #include "sx_video_sink.h"
12 |
13 | // ========================================================
14 | // Constants
15 | // ========================================================
16 |
17 | // ========================================================
18 | // Private Types
19 | // ========================================================
20 |
21 | // ========================================================
22 | // Private Variables & Functions
23 | // ========================================================
24 |
25 | static COMPONENT_T *video_decode;
26 | static COMPONENT_T *video_scheduler;
27 | static COMPONENT_T *video_render;
28 | static COMPONENT_T *video_clock;
29 | static COMPONENT_T *comp_list[5];
30 | static TUNNEL_T tunnel[4];
31 | static ILCLIENT_T *client;
32 |
33 | static unsigned int port_setting_changed = 0;
34 | static unsigned int first_packet = 1;
35 |
36 | //#define WRITE_TO_FILE 1
37 |
38 | #if WRITE_TO_FILE
39 | static FILE * write_ptr;
40 | #endif
41 |
42 | // ========================================================
43 | // Public Functions
44 | // ========================================================
45 |
46 | // --------------------------------------------------------
47 | // decoder_hw_init
48 | // Initializes decoder hardware.
49 | //
50 | void sx_video_sink_init(
51 | void
52 | )
53 | {
54 | OMX_VIDEO_PARAM_PORTFORMATTYPE format;
55 | OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
56 | int rc;
57 |
58 |
59 | memset(comp_list, 0, sizeof(comp_list));
60 | memset(tunnel, 0, sizeof(tunnel));
61 |
62 | // Initialize Broadcom host.
63 | bcm_host_init();
64 |
65 | // initialize il client.
66 | client = ilclient_init();
67 | assert(client != NULL);
68 |
69 | // initialize omx.
70 | rc = OMX_Init();
71 | assert(rc == OMX_ErrorNone);
72 |
73 | // Create decoder component.
74 | rc = ilclient_create_component(client,
75 | &video_decode,
76 | "video_decode",
77 | ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS);
78 | assert(rc == 0);
79 |
80 | comp_list[0] = video_decode;
81 |
82 | // Create video renderer.
83 | rc = ilclient_create_component(client,
84 | &video_render,
85 | "video_render",
86 | ILCLIENT_DISABLE_ALL_PORTS);
87 | assert(rc == 0);
88 |
89 | comp_list[1] = video_render;
90 |
91 | // Create clock.
92 | rc = ilclient_create_component(client,
93 | &video_clock,
94 | "clock",
95 | ILCLIENT_DISABLE_ALL_PORTS);
96 | assert(rc == 0);
97 |
98 | comp_list[2] = video_clock;
99 |
100 | // Configure clock.
101 | memset(&cstate, 0, sizeof(cstate));
102 | cstate.nSize = sizeof(cstate);
103 | cstate.nVersion.nVersion = OMX_VERSION;
104 | cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
105 | cstate.nWaitMask = 1;
106 |
107 | rc = OMX_SetParameter(ILC_GET_HANDLE(video_clock),
108 | OMX_IndexConfigTimeClockState,
109 | &cstate);
110 | assert(rc == 0);
111 |
112 | // Create clock.
113 | rc = ilclient_create_component(client,
114 | &video_scheduler,
115 | "video_scheduler",
116 | ILCLIENT_DISABLE_ALL_PORTS);
117 | assert(rc == 0);
118 |
119 | comp_list[3] = video_scheduler;
120 |
121 | // Set tunnels.
122 |
123 | // Connect decode to scheduler.
124 | set_tunnel(tunnel, video_decode, 131, video_scheduler, 10);
125 |
126 | // Connect scheduler to renderer.
127 | set_tunnel(tunnel+1, video_scheduler, 11, video_render, 90);
128 |
129 | // Connect clock to scheduler.
130 | set_tunnel(tunnel+2, video_clock, 80, video_scheduler, 12);
131 |
132 | // Setup clock tunnel first.
133 | rc = ilclient_setup_tunnel(tunnel+2, 0, 0);
134 | assert(rc == 0);
135 |
136 | // Kick start the clock.
137 | ilclient_change_component_state(video_clock, OMX_StateExecuting);
138 |
139 | #define AUTO_FULLSCREEN
140 | //
141 | // UINT32 sess_width = sx_mgmt_env_get(MGMT_ENV_VAR_SESSION_WIDTH);
142 | // UINT32 sess_height = sx_mgmt_env_get(MGMT_ENV_VAR_SESSION_HEIGHT);
143 |
144 | #if 1
145 | OMX_CONFIG_DISPLAYREGIONTYPE drt;
146 | memset(&drt, 0, sizeof(drt));
147 | drt.nVersion.nVersion = OMX_VERSION;
148 | drt.nSize = sizeof(drt);
149 | drt.nPortIndex = 90;
150 | #if !defined(AUTO_FULLSCREEN)
151 | drt.src_rect.x_offset = 0;
152 | drt.src_rect.y_offset = 0;
153 | drt.src_rect.width = sx_mgmt_env_get(MGMT_ENV_VAR_SESSION_WIDTH);
154 | drt.src_rect.height = sx_mgmt_env_get(MGMT_ENV_VAR_SESSION_HEIGHT);
155 | drt.dest_rect.x_offset = -56;
156 | drt.dest_rect.y_offset = 0;
157 | drt.dest_rect.width = 1792;
158 | drt.dest_rect.height = 1050;
159 | #endif
160 | #if !defined(AUTO_FULLSCREEN)
161 | drt.fullscreen = OMX_FALSE;
162 | #else
163 | drt.fullscreen = OMX_TRUE;
164 | #endif
165 | drt.noaspect = OMX_TRUE;
166 | drt.mode = OMX_DISPLAY_MODE_FILL;
167 |
168 | #if !defined(AUTO_FULLSCREEN)
169 | drt.set = (OMX_DISPLAYSETTYPE) ( OMX_DISPLAY_SET_SRC_RECT |
170 | OMX_DISPLAY_SET_DEST_RECT |
171 | OMX_DISPLAY_SET_FULLSCREEN |
172 | OMX_DISPLAY_SET_NOASPECT);
173 | #else
174 | drt.set = (OMX_DISPLAYSETTYPE) ( OMX_DISPLAY_SET_FULLSCREEN |
175 | OMX_DISPLAY_SET_NOASPECT);
176 | #endif
177 |
178 | rc = OMX_SetConfig(ILC_GET_HANDLE(video_render), OMX_IndexConfigDisplayRegion, &drt);
179 | assert(rc == 0);
180 | #endif
181 |
182 | // Kick start video decoder.
183 | ilclient_change_component_state(video_decode, OMX_StateIdle);
184 |
185 | // Configure decoder.
186 | memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
187 | format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
188 | format.nVersion.nVersion = OMX_VERSION;
189 | format.nPortIndex = 130;
190 | format.eCompressionFormat = OMX_VIDEO_CodingAVC;
191 |
192 | rc = OMX_SetParameter(ILC_GET_HANDLE(video_decode),
193 | OMX_IndexParamVideoPortFormat,
194 | &format);
195 | assert(rc == 0);
196 |
197 | // Enable video decode.
198 | rc = ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL);
199 | assert(rc == 0);
200 |
201 | // Kick start video decoder.
202 | ilclient_change_component_state(video_decode, OMX_StateExecuting);
203 |
204 | #if WRITE_TO_FILE
205 | write_ptr = fopen("video_sink.h264", "wb");
206 | #endif
207 |
208 | printf("decoder_hw: initialized");
209 | }
210 |
211 |
212 | // --------------------------------------------------------
213 | // decoder_hw_get_buf
214 | // Get decoder hardware buffer.
215 | //
216 | sDECODER_HW_BUFFER * sx_video_sink_buf_get(
217 | void
218 | )
219 | {
220 | OMX_BUFFERHEADERTYPE *buf;
221 |
222 |
223 | // Attempt to get a buffer.
224 | buf = ilclient_get_input_buffer(video_decode, 130, 0);
225 |
226 | // Typecase to our overlay and return.
227 | return (sDECODER_HW_BUFFER *) buf;
228 | }
229 |
230 |
231 | // --------------------------------------------------------
232 | // decoder_hw_set_buf
233 | // Set decoder hardware buffer.
234 | //
235 | void sx_video_sink_buf_set(
236 | sDECODER_HW_BUFFER *decoder_hw_buf
237 | )
238 | {
239 | #define MAX_BYTES_ALLOWED (16 << 10)
240 | OMX_BUFFERHEADERTYPE *buf;
241 | int rc;
242 |
243 |
244 | buf = (OMX_BUFFERHEADERTYPE *) decoder_hw_buf;
245 |
246 | #if WRITE_TO_FILE
247 | fwrite(decoder_hw_buf->buffer, decoder_hw_buf->buffer_len, 1, write_ptr);
248 | #endif
249 |
250 | if( !port_setting_changed
251 | && (ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0))
252 | {
253 | printf("(decoder_hw): port setting changed!\n");
254 |
255 | port_setting_changed = 1;
256 |
257 | // Setup tunnel for ...
258 | rc = ilclient_setup_tunnel(tunnel, 0, 0);
259 | assert(rc == 0);
260 |
261 | // Kick start scheduler.
262 | ilclient_change_component_state(video_scheduler, OMX_StateExecuting);
263 |
264 | rc = ilclient_setup_tunnel(tunnel+1, 0, 1000);
265 | assert(rc == 0);
266 |
267 | // Kick start renderer.
268 | ilclient_change_component_state(video_render, OMX_StateExecuting);
269 | }
270 |
271 | // Set buffer property.
272 | buf->nOffset = 0;
273 | buf->nFlags = first_packet ? OMX_BUFFERFLAG_STARTTIME : OMX_BUFFERFLAG_TIME_UNKNOWN;
274 | first_packet = 0;
275 |
276 | // FLush into the decoder.
277 | rc = OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf);
278 | assert(rc == 0);
279 | }
280 |
281 |
--------------------------------------------------------------------------------