as the title suggests im trying to make two STM boards talk to each other. The problem is, is the master can send, and the slave can receive. But the slave cant transmit anything. I checked it on an analyzer and the only thing the slave is sending is 0xFF.
(Chip Select is in software)
So im looking for help, or maybe an explanation.
MASTER:
#include "main.h"
#include "stm32f1xx_hal.h"
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi2;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI2_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
void print(char * buffer)
{
HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
}
/* USER CODE END 0 */
/**
* #brief The application entry point.
*
* #retval None
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
for(uint8_t i = 0; ;i++)
{
int result = 0;
GPIOB->BSRR = (1 << 12);
HAL_SPI_TransmitReceive(&hspi2, (uint8_t *)&i, (uint8_t*)&result, 2, HAL_MAX_DELAY);
GPIOB->BRR = (1 << 12);
if (result != (i - 1))
{
print("nop");
}
HAL_Delay(10);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* SPI2 init function */
static void MX_SPI2_Init(void)
{
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12|GPIO_PIN_5, GPIO_PIN_SET);
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : PB10 */
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PB12 PB5 */
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
SLAVE:
#include "main.h"
#include "stm32f1xx_hal.h"
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi2;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI2_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
void print(char * buffer)
{
HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
}
/* USER CODE END 0 */
/**
* #brief The application entry point.
*
* #retval None
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
SPI2->CR1 |= 1UL << 9;
SPI2->CR1 |= 1UL << 8;
while (1)
{
if(GPIOB->IDR & (1 << 10))
{
SPI2->CR1 &= ~(1UL << 8);
HAL_SPI_TransmitReceive(&hspi2, (uint8_t *)&output,(uint8_t*)&input, 1, HAL_MAX_DELAY);
output = input;
SPI2->CR1 |= 1UL << 8;
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* SPI2 init function */
static void MX_SPI2_Init(void)
{
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, RowPins_Pin|RowPinsA9_Pin|RowPinsA10_Pin|RowPinsA11_Pin
|RowPinsA12_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : ColumnPins_Pin ColumnPinsA1_Pin ColumnPinsA2_Pin ColumnPinsA3_Pin
ColumnPinsA4_Pin ColumnPinsA5_Pin ColumnPinsA6_Pin */
GPIO_InitStruct.Pin = ColumnPins_Pin|ColumnPinsA1_Pin|ColumnPinsA2_Pin|ColumnPinsA3_Pin
|ColumnPinsA4_Pin|ColumnPinsA5_Pin|ColumnPinsA6_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : PB10 */
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : RowPins_Pin RowPinsA9_Pin RowPinsA10_Pin RowPinsA11_Pin
RowPinsA12_Pin */
GPIO_InitStruct.Pin = RowPins_Pin|RowPinsA9_Pin|RowPinsA10_Pin|RowPinsA11_Pin
|RowPinsA12_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : PB5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
Master has to send data and generate the clock for the slave. So if you expecting something to be received from the slave you need to send the same number of dummy data.
This is how the SPI works.
The master to receive data must transmit at the same time. Slave to transmit has to wait for the clock signal - and it is generated by the master when transmitting.
BTW HAL SPI implementation (USART as well) is horrible. Use bare registers instead.
Related
I need to implement trickplay mode in rtsp-server by sending seek-event to an GstElement. Pipeline: (appsrc name=vsrc !h264parse ! rtph264pay pt=96 name=pay0)
But if i send seek-event to any of 3 GstElements - function gst_element_send_event return 0, so it doesn't work.
What am I doing wrong? Or is there any another approach to implement trickplay mode on rtsp-server?
#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
#include <string>
#include <fstream>
static GstElement *pMy = NULL;
static GstElement *pMy2 = NULL;
static gboolean timeout(GstRTSPServer * server)
{
GstRTSPSessionPool *pool;
pool = gst_rtsp_server_get_session_pool(server);
gst_rtsp_session_pool_cleanup(pool);
g_object_unref(pool);
return TRUE;
}
static void onNeedVideoData(GstElement * appsrc)
{
static int NN = 0;
++NN;
int Size = sFileSize(NN);
GstBuffer* buf = gst_buffer_new_and_alloc(Size);
GstMapInfo map;
gst_buffer_map(buf, &map, GST_MAP_WRITE);
FILE *fp = fopen(std::string("C:\\rtsp_files\\body" + std::to_string(NN) + ".bin").c_str(), "rb");
fread(map.data, sizeof(unsigned char), Size, fp);
fclose(fp);
gst_buffer_unmap(buf, &map);
//in random moment we send seek-event to some GstElement
if (NN % 300 == 0){
double dspeed = 4.;
gint64 position;
if (!gst_element_query_position(pMy, GST_FORMAT_TIME, &position)) {
g_printerr("Unable to retrieve current position.\n");
return;
}
GstEvent * seek_event = gst_event_new_seek(dspeed, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, 0);
auto res1 = gst_element_send_event(pMy2, seek_event);
g_print("%d\n", res1);
}
GstFlowReturn ret;
g_signal_emit_by_name(appsrc, "push-buffer", buf, &ret);
gst_buffer_unref(buf);
}
static void need_video_data(GstElement * appsrc, guint unused)
{
onNeedVideoData(appsrc);
}
static void media_constructed(GstRTSPMediaFactory * factory, GstRTSPMedia * media)
{
GstElement* element = pMy = gst_rtsp_media_get_element(media);
GstElement* vsrc = gst_bin_get_by_name_recurse_up(GST_BIN(element), "vsrc");
g_signal_connect(vsrc, "need-data", (GCallback)need_video_data, NULL);
pMy2 = gst_bin_get_by_name_recurse_up(GST_BIN(element), "h264parse0");
}
int main(int argc, char *argv[])
{
GMainLoop *loop;
GstRTSPServer *server;
GstRTSPMountPoints *mounts;
GstRTSPMediaFactory *factory;
gst_init(&argc, &argv);
loop = g_main_loop_new(NULL, FALSE);
/* create a server instance */
server = gst_rtsp_server_new();
/* get the mount points for this server, every server has a default object
* that be used to map uri mount points to media factories */
mounts = gst_rtsp_server_get_mount_points(server);
/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d. Each
* element with pay%d names will be a stream */
factory = gst_rtsp_media_factory_new();
gst_rtsp_media_factory_set_launch(factory, "( "
"appsrc name=vsrc !"
"h264parse ! rtph264pay pt=96 name=pay0 )");
gst_rtsp_media_factory_set_shared(factory, TRUE);
g_signal_connect(factory, "media-constructed", (GCallback)
media_constructed, NULL);
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory(mounts, "/test", factory);
/* don't need the ref to the mapper anymore */
g_object_unref(mounts);
/* attach the server to the default maincontext */
if (gst_rtsp_server_attach(server, NULL) == 0)
goto failed;
/* add a timeout for the session cleanup */
g_timeout_add_seconds(2, (GSourceFunc)timeout, server);
g_print("stream ready at rtsp://127.0.0.1:8554/test\n");
g_main_loop_run(loop);
return 0;
/* ERRORS */
failed:
{
g_print("failed to attach the server\n");
return -1;
}
}
I solved my own problem:
#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
#include <string>
#include <fstream>
static GstElement *pMediaElement = NULL;
/* this timeout is periodically run to clean up the expired sessions from the
* pool. This needs to be run explicitly currently but might be done
* automatically as part of the mainloop. */
static gboolean
timeout(GstRTSPServer * server)
{
GstRTSPSessionPool *pool;
pool = gst_rtsp_server_get_session_pool(server);
gst_rtsp_session_pool_cleanup(pool);
g_object_unref(pool);
return TRUE;
}
static int sFileSize(const std::string &filename)
{
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
return in.tellg();
}
static void onNeedVideoData(GstElement * appsrc)
{
static int NN = 0;
++NN;
std::string filename = "C:\\rtsp_files\\body" + std::to_string(NN) + ".bin";
int Size = sFileSize(filename);
GstBuffer* buf = gst_buffer_new_and_alloc(Size);
GstMapInfo map;
gst_buffer_map(buf, &map, GST_MAP_WRITE);
FILE *fp = fopen(filename.c_str(), "rb");
fread(map.data, sizeof(unsigned char), Size, fp);
fclose(fp);
gst_buffer_unmap(buf, &map);
//in random moment we send seek-event to MediaElement
if (NN == 300){
gint64 position;
if (!gst_element_query_position(pMediaElement, GST_FORMAT_TIME, &position)) {
g_printerr("Unable to retrieve current position.\n");
return;
}
GstEvent * seek_event = gst_event_new_seek(4., GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, 0);
auto res = gst_element_send_event(pMediaElement, seek_event);
g_print("%d\n", res);
}
GstFlowReturn ret;
g_signal_emit_by_name(appsrc, "push-buffer", buf, &ret);
gst_buffer_unref(buf);
}
static void need_video_data(GstElement * appsrc, guint unused)
{
onNeedVideoData(appsrc);
}
/* called when appsrc wants us to return data from a new position with the next
* call to push-buffer. */
static gboolean seek_data(GstElement * appsrc, guint64 position)
{
g_print("seek_data call\n");
//GST_DEBUG("seek to offset %" G_GUINT64_FORMAT, position);
//app->offset = position;
return TRUE;
}
static void media_constructed(GstRTSPMediaFactory * factory, GstRTSPMedia * media)
{
GstElement* element = pMediaElement = gst_rtsp_media_get_element(media);
GstElement* vsrc = gst_bin_get_by_name_recurse_up(GST_BIN(element), "vsrc");
gst_util_set_object_arg(G_OBJECT(vsrc), "stream-type", "seekable");
g_signal_connect(vsrc, "need-data", (GCallback)need_video_data, NULL);
g_signal_connect(vsrc, "seek-data", G_CALLBACK(seek_data), NULL);
}
int main(int argc, char *argv[])
{
GMainLoop *loop;
GstRTSPServer *server;
GstRTSPMountPoints *mounts;
GstRTSPMediaFactory *factory;
gst_init(&argc, &argv);
loop = g_main_loop_new(NULL, FALSE);
/* create a server instance */
server = gst_rtsp_server_new();
/* get the mount points for this server, every server has a default object
* that be used to map uri mount points to media factories */
mounts = gst_rtsp_server_get_mount_points(server);
/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d. Each
* element with pay%d names will be a stream */
factory = gst_rtsp_media_factory_new();
gst_rtsp_media_factory_set_launch(factory, "( "
"appsrc name=vsrc !"
"h264parse config-interval=1 ! rtph264pay pt=96 name=pay0 )");
gst_rtsp_media_factory_set_shared(factory, TRUE);
g_signal_connect(factory, "media-constructed", (GCallback)
media_constructed, NULL);
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory(mounts, "/test", factory);
/* don't need the ref to the mapper anymore */
g_object_unref(mounts);
/* attach the server to the default maincontext */
if (gst_rtsp_server_attach(server, NULL) == 0)
goto failed;
/* add a timeout for the session cleanup */
g_timeout_add_seconds(2, (GSourceFunc)timeout, server);
/* start serving, this never stops */
g_print("stream ready at rtsp://127.0.0.1:8554/test\n");
g_main_loop_run(loop);
return 0;
/* ERRORS */
failed:
{
g_print("failed to attach the server\n");
return -1;
}
}
I try to implement a new Type that has the same function of PyDictObject. But I found that it runs much slower than PyDictObject.
Here is my new Type of python extending.
typedef struct
{
PyObject_HEAD
PyDictObject *m;
} AttrCache;
static Py_ssize_t
cache_length(AttrCache* self)
{
return self->m->ma_used;
}
static PyObject *
cache_subscript(AttrCache* self, register PyObject*key)
{
PyMappingMethods *m;
m = self->m->ob_type->tp_as_mapping;
return m->mp_subscript(self->m, key);
//return dict_subscript(self->m, key);
}
static int
cache_ass_sub(AttrCache* self, PyObject *v, PyObject *w)
{
if(w == NULL)
return PyDict_DelItem((PyObject*)self->m, v);
else
return PyDict_SetItem((PyObject*)self->m, v, w);
}
static PyMappingMethods cache_as_mapping = {
(lenfunc)cache_length,
(binaryfunc)cache_subscript,
(objobjargproc)cache_ass_sub,
};
int
Cache_contains(AttrCache* self, PyObject* key)
{
return PyDict_Contains((PyObject*)self->m, key);
}
static PySequenceMethods cache_as_sequence = {
0, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
Cache_contains, /* sq_contains */
0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */
};
static PyTypeObject AttrCacheType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"attrcache.AttrCacheType", /* tp_name */
sizeof(AttrCache), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
&cache_as_sequence, /* tp_as_sequence */
&cache_as_mapping, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, //AttrCacheMethods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
AttrCacheNew, /* tp_new */
};
After I finished building the code above, I tested the performance. And the result was really bad. Here is my test code
import attrcache
import time
pyDict = dict()
cDict = attrcache.AttrCache()
total = 10000000
keys = map(str, range(0, total))
print "init keys done"
start = time.time()
for key in keys:
pyDict[key] = 1
print "py init cost ", time.time() - start
start - time.time()
for key in keys:
cDict[key] = 1
print "c init cost ", time.time() - start
I was confused by the result. The py dict cost about 5 seconds while my c dict cost about 10 seconds.
Is there anything wrong with my code?
I have been trying to do sip_init for multiple sip thread in pjsip stack, but i am not able init for multi threads and if possible then how can we get values of different threads from same variables.
I am adding here the code that i have tried with.
#include<stdio.h>
#include<stdlib.h>
#include <pthread.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <pjsip.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>
#include <pjsip_ua.h>
#include <pjsip_simple.h>
#include <pjlib-util.h>
#include <pjlib.h>
static __thread trunk_t *sip_trunk;
static void *sip_init(trunk_t *trunk)
{
pj_pool_t *pool = NULL;
pj_status_t status;
pjmedia_codec_mgr *codec_mgr;
int i;
struct event *ev;
struct timeval tv;
struct in_addr listen_addr;
sip_trunk = trunk;
/* Must init PJLIB first: */
status = pj_init();
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
pj_log_set_level(5);
/* Then init PJLIB-UTIL: */
status = pjlib_util_init();
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
sip_thread_reg_process();
tv.tv_sec = 0;
tv.tv_usec = 100000;
ev = event_new(trunk->rt_thr_ess->proto_evbase, -1, EV_READ|EV_PERSIST, rx_data, NULL);
event_add(ev, &tv);
/* Create global endpoint: */
const pj_str_t *hostname;
const char *endpt_name;
/* Endpoint MUST be assigned a globally unique name.
* The name will be used as the hostname in Warning header.
*/
/* For this implementation, we'll use hostname for simplicity */
hostname = pj_gethostname();
endpt_name = hostname->ptr;
/* Create the endpoint: */
status = pjsip_endpt_create(&cp.factory, endpt_name, &g_endpt);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/*
* Add UDP transport, with hard-coded port
* Alternatively, application can use pjsip_udp_transport_attach() to
* start UDP transport, if it already has an UDP socket (e.g. after it
* resolves the address with STUN).
*/
pj_sockaddr addr;
pjsip_tpfactory *tpfactory;
for(i=0; i < 1; ++i) {
listen_addr.s_addr = trunk->listen_ip;
pj_str_t ip_str = pj_str(strdup(inet_ntoa(listen_addr)));
pj_sockaddr_init(AF, &addr, &ip_str, (pj_uint16_t)trunk- >listen_port);
if(AF == pj_AF_INET()) {
status = pjsip_udp_transport_start( g_endpt, &addr.ipv4, NULL,
1, &transport[i]);
status = pjsip_tcp_transport_start( g_endpt, &addr.ipv4, 1, & tpfactory);
} else if(AF == pj_AF_INET6()) {
status = pjsip_udp_transport_start6(g_endpt, &addr.ipv6, NULL,
1, NULL);
} else {
status = PJ_EAFNOTSUP;
}
if(status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to start UDP transport", status);
return NULL;
}
}
/*
* Init transaction layer.
* This will create/initialize transaction hash tables etc.
*/
status = pjsip_tsx_layer_init_module(g_endpt);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/*
* Initialize UA layer module.
* This will create/initialize dialog hash tables etc.
*/
status = pjsip_ua_init_module( g_endpt, NULL );
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/*
* Init invite session module.
* The invite session module initialization takes additional argument,
* i.e. a structure containing callbacks to be called on specific
* occurence of events.
*
* The on_state_changed and on_new_session callbacks are mandatory.
* Application must supply the callback function.
*
* We use on_media_update() callback in this application to start
* media transmission.
*/
pjsip_inv_callback inv_cb;
/* Init the callback for INVITE session: */
pj_bzero(&inv_cb, sizeof(inv_cb));
inv_cb.on_state_changed = &call_on_state_changed;
inv_cb.on_new_session = &call_on_forked;
inv_cb.on_media_update = &call_on_media_update;
inv_cb.on_rx_offer = &call_on_rx_offer;
/* Initialize invite session module: */
status = pjsip_inv_usage_init(g_endpt, &inv_cb);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/* Initialize 100rel support */
status = pjsip_100rel_init_module(g_endpt);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/*
* Register our module to receive incoming requests.
*/
status = pjsip_endpt_register_module(g_endpt, &mod_ics);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/*
* Register message logger module.
*/
status = pjsip_endpt_register_module( g_endpt, &msg_logger);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/*
* Initialize media endpoint.
* This will implicitly initialize PJMEDIA too.
*/
status = pjmedia_endpt_create(&cp.factory,
pjsip_endpt_get_ioqueue(g_endpt),
0, &g_med_endpt);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/* Initializing g711 codec */
#if CODEC_G711
status = pjmedia_codec_g711_init(g_med_endpt);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
/*
* Setting PCMA as the Highest priority codec */
codec_mgr = pjmedia_endpt_get_codec_mgr(g_med_endpt);
pj_str_t codec_id = pj_str("PCMA/8000/1");
pjmedia_codec_mgr_set_codec_priority(codec_mgr, &codec_id, PJMEDIA_CODEC_PRIO_HIGHEST);
#endif
/* Initializing g722 codec */
#if CODEC_G722
status = pjmedia_codec_g722_init(g_med_endpt);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
#endif
#if CODEC_G729
/* Initializing g729 codec */
status = pjmedia_codec_g729_init(g_med_endpt);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
#endif
#endif
pool = pjsip_endpt_create_pool(g_endpt, "Generic Pool", 512, 512);
pj_str_t realm_str = pj_str("google.com");
status = pjsip_auth_srv_init(pool, &auth_server, &realm_str, digest_lookup, PJSIP_AUTH_SRV_IS_PROXY);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
#if ENABLE_VIDEO
/* Only for Video this video format manager creation done */
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
#endif
#if H264_CODE
PJ_ASSERT_RETURN(status == PJ_SUCCESS, NULL);
#endif
return NULL;
}
int main()
{
trunk_t *sip_trunk;
trunk_t *sip_anthr_trunk;
pthread_t sid;
pthread_t tid;
pthread_create(&sid, NULL, sip_init, sip_trunk);
pthread_join(sid, NULL);
pthread_create(&tid, NULL, sip_init, sip_anthr_trunk);
pthread_join(tid, NULL);
return 0;
}
I want to get "2 signals" when I read an audio file. I know that I must use the FFmpeg function av_read_frame, but I have just that I call "1 signal". How can I have multiple signals to treat each signal in different way ?
My code is like that :
while (av_read_frame(pFormatCtx, packet) >= 0)
{
/* AVPacket == Audio */
if (packet->stream_index == audioStream)
{
/* Décodage des packets */
ret = avcodec_decode_audio4(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0)
{
fprintf(stderr, "%s\n", "Error in decoding audio frame");
return (-1);
}
if (got_picture > 0)
{
/* Convertissage de l'audio */
swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)pFrame->data, pFrame->nb_samples);
#if 1
/* Affichage des informations dans la console */
printf("Index : %5d\t Points : %lld\t Packet size : %d\n", index, packet->pts, packet->size);
#endif /* 1 */
#if OUTPUT_PCM
/* Fonction pour écrire dans le fichier */
fwrite(out_buffer, 1, out_buffer_size, pFile);
#endif /* OUTPUT_PCM */
/* Incrémentation */
index = index + 1;
}
#if USE_SDL
while (audio_len > 0)
SDL_Delay(1);
/* Attribution des valeurs avec les variables globales */
audio_chunk = (Uint8 *)out_buffer;
audio_len = out_buffer_size;
audio_pos = audio_chunk;
SDL_PauseAudio(0);
#endif /* USE_SDL */
}
/* Libérer la structure AVPacket */
av_free_packet(packet);
}
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#define PORT1 0x2E8 /* Port Address Goes Here */
/* Defines Serial Ports Base Address */
/* COM4 0x2E8 */
#define INTVECT 0x0B /* Com Port's IRQ here */
/* (Must also change PIC setting) */
int bufferin = 0;
int bufferout = 0;
char ch;
char buffer[1025];
void interrupt PORT1INT() /* Interrupt Service Routine (ISR) for PORT1 */
{
int c;
do {
c = inportb(PORT1 + 5);
if (c & 1) {
buffer[bufferin] = inportb(PORT1);
bufferin++;
if (bufferin == 1024) bufferin = 0;
}
} while (c & 1);
outportb(0x20, 0x20);
}
void main(void)
{
int c;
//outportb(PORT1 + 1, 0); /* Turn off interrupts - Port1 */
//oldport1isr = getvect(INTVECT); /* Save old Interrupt Vector for */
/* later recovery */
setvect(INTVECT, PORT1INT); /* Set Interrupt Vector Entry */
/* COM1 - 0x0C */
/* COM2 - 0x0B */
/* COM3 - 0x0C */
/* COM4 - 0x0B */
outportb(PORT1 +3 , 0x80); /* SET DLAB ON */
outportb(PORT1 +0, 0x03); /* Set Baud rate - Divisor Latch Low Byte */
/* Default 0x03 = 38,400 BPS */
/* 0x01 = 115,200 BPS */
/* 0x02 = 56,700 BPS */
/* 0x06 = 19,200 BPS */
/* 0x0C = 9,600 BPS */
/* 0x18 = 4,800 BPS */
/* 0x30 = 2,400 BPS */
outportb(PORT1 + 1, 0x00); /* Set Baud rate - Divisor Latch High Byte */
outportb(PORT1 + 3, 0x03); /* 8 Bits, No Parity, 1 Stop Bit */
outportb(PORT1 + 2, 0xC7); /* FIFO Control Register */
outportb(PORT1 + 4, 0x0B); /* Turn on DTR, RTS, and OUT2 */
outportb(0x21, (inportb(0x21) & 0xF7)); /* Set Programmable Interrupt */
/* Controller */
/* COM1 (IRQ4) - 0xEF */
/* COM2 (IRQ3) - 0xF7 */
/* COM3 (IRQ4) - 0xEF */
/* COM4 (IRQ3) - 0xF7 */
outportb(PORT1 + 1, 0x01); /* Interrupt when data received */
printf("\nSample Comm's Program. Press ESC to quit \n");
do {
if (bufferin != bufferout){
ch = buffer[bufferout];
bufferout++;
if (bufferout == 1024) bufferout = 0;
printf("%c", ch);
}
if (kbhit()){
c = getch();
outportb(PORT1, c);
}
} while
(c != 27);
outportb(PORT1 + 1, 0); /* Turn off interrupts - Port1 */
outportb(0x21, (inportb(0x21) | 0x08)); /* MASK IRQ using PIC */
/* COM1 (IRQ4) - 0x10 */
/* COM2 (IRQ3) - 0x08 */
/* COM3 (IRQ4) - 0x10 */
/* COM4 (IRQ3) - 0x08 */
setvect(INTVECT, oldport1isr); /* Restore old interrupt vector */
}
So I have to send some data from an UART to an UART using COM4 Serial Port, I have this small program here as an example but can't figure out why I can't compile it in Visual Studion ( C++ Win32 Project )
Any ideas? I also have to implement an timer with RQ3.
It can't compile because access to the hardware is managed by the OS. Your example states in the very first line which OS it applies to, and it's not Windows.
As for your second claim, you don't. IRQ3 is not used for timers in Windows programs. There are plenty of answers about timers already on StackOverflow, so check that first.