├── .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 | --------------------------------------------------------------------------------