first add sdk

This commit is contained in:
jialexd 2019-04-02 16:34:25 +08:00
commit f91efd1250
3915 changed files with 1291882 additions and 0 deletions

View file

@ -0,0 +1,137 @@
#include "mmf_sink.h"
#include "i2s_api.h"
#include "g711/g711_codec.h"
#define BUF_BLK 3 //MUST BE GREATER OR EQUAL TO 2
static u8 i2s_dec_buf[320]; //store decoded data
static u8 i2s_chl_buf[640*(BUF_BLK+1)]; //store mono2stereo data
#define I2S_DMA_PAGE_NUM 2
#define I2S_DMA_PAGE_SIZE (640)
static u8 i2s_tx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
static u8 i2s_rx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
#define I2S_SCLK_PIN PC_1
#define I2S_WS_PIN PC_0
#define I2S_SD_PIN PC_2
static u32 update_flag = 0;
static u32 update_token = 0;
static u32 prev_token = 0;
u8 *play_ptr = i2s_chl_buf;
static void i2s_tx_complete(void *data, char* pbuf){
i2s_t *obj = (i2s_t *)data;
int *ptx_buf;
ptx_buf = i2s_get_tx_page(obj);
if(update_token > prev_token)
update_flag = 1;
else
update_flag = 0;
if(update_flag)
{
_memcpy((void*)ptx_buf, (void*)play_ptr, I2S_DMA_PAGE_SIZE);
play_ptr += I2S_DMA_PAGE_SIZE;
if(play_ptr >= i2s_chl_buf + BUF_BLK*I2S_DMA_PAGE_SIZE)
{
play_ptr = i2s_chl_buf;
}
update_token--;
}
else
_memset((void*)ptx_buf, 0, I2S_DMA_PAGE_SIZE);
i2s_send_page(obj, (uint32_t*)ptx_buf);
//printf("\n\r%d", update_token);
}
static void i2s_rx_complete(void *data, char* pbuf){
return;
}
void i2s_sink_mod_close(void* ctx)
{
i2s_t* i2s_obj = (i2s_t*) ctx;
i2s_deinit(i2s_obj);
free(i2s_obj);
}
void* i2s_sink_mod_open(void)
{
i2s_t* i2s_obj = malloc(sizeof(i2s_t));
if(i2s_obj == NULL)
return NULL;
alc5651_init();
alc5651_init_interface2(); // connect to ALC interface 2
//default setting i2s obj
i2s_obj->channel_num = /*CH_MONO*/CH_STEREO;
i2s_obj->sampling_rate = I2S_SR_8KHZ;
i2s_obj->word_length = WL_16b;
i2s_obj->direction = I2S_DIR_TX;
i2s_init(i2s_obj, I2S_SCLK_PIN, I2S_WS_PIN, I2S_SD_PIN);
i2s_set_dma_buffer(i2s_obj, (char*)i2s_tx_buf, (char*)i2s_rx_buf, \
I2S_DMA_PAGE_NUM, I2S_DMA_PAGE_SIZE);
i2s_tx_irq_handler(i2s_obj, (i2s_irq_handler)i2s_tx_complete, (uint32_t)i2s_obj);
i2s_rx_irq_handler(i2s_obj, (i2s_irq_handler)i2s_rx_complete, (uint32_t)i2s_obj);
return i2s_obj;
}
int i2s_sink_mod_set_param(void* ctx, int cmd, int arg)
{
i2s_t* i2s_obj = (i2s_t*) ctx;
switch(cmd){
case CMD_SET_STREAMMING:
if(arg == ON){
i2s_send_page(i2s_obj, (uint32_t*)i2s_get_tx_page(i2s_obj));
}else{
}
break;
default:
break;
}
return 0;
}
//send audio data here
static int cache_byte = 0;
u8 *cache_ptr = i2s_chl_buf;
int i2s_sink_mod_handle(void* ctx, void* b)
{
i2s_t* i2s_obj = (i2s_t*) ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
if(exbuf->state != STAT_READY)
return -EAGAIN;
G711_decoder(exbuf->data, (short*)i2s_dec_buf, I2S_MODE_G711U, exbuf->len);
//mono2stereo(i2s_dec_buf, i2s_chl_buf, 320, 16);
mono2stereo(i2s_dec_buf, cache_ptr, exbuf->len*2, 16);
cache_byte += exbuf->len*4;
cache_ptr += exbuf->len*4;
if(cache_ptr >= i2s_chl_buf + BUF_BLK*I2S_DMA_PAGE_SIZE)
{
memcpy(i2s_chl_buf, i2s_chl_buf + BUF_BLK*I2S_DMA_PAGE_SIZE, cache_ptr - (i2s_chl_buf + BUF_BLK*I2S_DMA_PAGE_SIZE));
cache_ptr -= BUF_BLK*I2S_DMA_PAGE_SIZE;
}
if(cache_byte >= I2S_DMA_PAGE_SIZE)
{
cache_byte %= I2S_DMA_PAGE_SIZE;
//printf("\n\rcache:%dB", cache_byte);
update_token++;
}
//printf("\n\r%d", update_token);
while(update_token >= prev_token + BUF_BLK - 1)//MINUS 1 TO AVOID RING BUFFER OUT RACE
vTaskDelay(1);
exbuf->state = STAT_USED;
return 0;
}
msink_module_t i2s_sink_module =
{
.create = i2s_sink_mod_open,
.destroy = i2s_sink_mod_close,
.set_param = i2s_sink_mod_set_param,
.handle = i2s_sink_mod_handle,
};

View file

@ -0,0 +1,10 @@
#ifndef _STREAM_MODULES_H
#define _STREAM_MODULES_H
#include "../mmf_sink.h"
//list all avaliable modules here
extern msink_module_t rtsp_module;
extern msink_module_t rtsp2_module;
extern msink_module_t i2s_sink_module;
extern msink_module_t mp3_sink_module;
#endif

View file

@ -0,0 +1,109 @@
#include "mmf_sink_mp3.h"
/*SDRAM_DATA_SECTION*/ //unsigned char MP3_ip[640];
signed short WAV_op[4608];
#define I2S_DMA_PAGE_SIZE 4608 // 2 ~ 4096
#define I2S_DMA_PAGE_NUM 2 // Vaild number is 2~4
static u8 i2s_tx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
static u8 i2s_rx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
#define I2S_SCLK_PIN PC_1
#define I2S_WS_PIN PC_0
#define I2S_SD_PIN PC_2
static i2s_t i2s_obj;
mp3_decoder_t mp3;
mp3_info_t info;
int frame_size = 0;
int *ptx_buf;
static void i2s_tx_complete(void *data, char *pbuf)
{
//
}
static void i2s_rx_complete(void *data, char* pbuf)
{
//
}
void cleanup()
{
mp3_done(mp3);
}
void mp3_sink_mod_close(void* ctx)
{
cleanup();
}
void* mp3_sink_mod_open(void)
{
i2s_obj.channel_num = CH_STEREO;
i2s_obj.sampling_rate = I2S_SR_44p1KHZ;
i2s_obj.word_length = WL_16b;
i2s_obj.direction = I2S_DIR_TXRX;
i2s_init(&i2s_obj, I2S_SCLK_PIN, I2S_WS_PIN, I2S_SD_PIN);
i2s_set_dma_buffer(&i2s_obj, (char*)i2s_tx_buf, (char*)i2s_rx_buf, \
I2S_DMA_PAGE_NUM, I2S_DMA_PAGE_SIZE);
i2s_tx_irq_handler(&i2s_obj, (i2s_irq_handler)i2s_tx_complete, (uint32_t)&i2s_obj);
i2s_rx_irq_handler(&i2s_obj, (i2s_irq_handler)i2s_rx_complete, (uint32_t)&i2s_obj);
mp3 = mp3_create();
if(!mp3)
{
printf("mp3 context create fail\n");
cleanup();
}
#if CONFIG_EXAMPLE_MP3_STREAM_SGTL5000
sgtl5000_enable();
sgtl5000_setVolume(0.5);
#else
alc5651_init();
alc5651_init_interface2();
#endif
return (void*)1;
}
int mp3_sink_mod_set_param(void* ctx, int cmd, int arg)
{
return 1;
}
int mp3_sink_mod_handle(void* ctx, void* b)
{
exch_buf_t *exbuf = (exch_buf_t*)b;
if(exbuf->state != STAT_READY)
return -EAGAIN;
/* Read a block */
frame_size = mp3_decode(mp3, (exbuf->data), (exbuf->len), WAV_op, &info);
retry:
ptx_buf = i2s_get_tx_page(&i2s_obj);
if(ptx_buf){
if((frame_size>0)&&(info.audio_bytes>0))
{
memcpy((void*)ptx_buf, (void*)WAV_op, info.audio_bytes);
i2s_send_page(&i2s_obj, (uint32_t*)ptx_buf);
}
}else{
vTaskDelay(1);
goto retry;
}
exbuf->state = STAT_USED;
return 1;
}
msink_module_t mp3_sink_module =
{
.create = mp3_sink_mod_open,
.destroy = mp3_sink_mod_close,
.set_param = mp3_sink_mod_set_param,
.handle = mp3_sink_mod_handle,
};

View file

@ -0,0 +1,19 @@
#ifndef MMF_SINK_MP3_FILE_H
#define MMF_SINK_MP3_FILE_H
#include "mmf_sink.h"
#include "FreeRTOS.h"
#include "task.h"
#include "platform_opts.h"
#include "mp3/mp3_codec.h"
#include "diag.h"
#include "i2s_api.h"
#include "analogin_api.h"
#include <stdlib.h>
#include "section_config.h"
#if CONFIG_EXAMPLE_MP3_STREAM_SGTL5000
#include "sgtl5000.h"
#else
#include "alc5651.h"
#endif
#endif /* MMF_SINK_MP3_FILE_H */

View file

@ -0,0 +1,210 @@
#include "ff.h"
#include <fatfs_ext/inc/ff_driver.h>
#include <platform/platform_stdlib.h>
#include "basic_types.h"
#include "section_config.h"
#include "sdio_host.h"
#include <disk_if/inc/sdcard.h>
#include "FreeRTOS.h"
#include "task.h"
#include <platform/platform_stdlib.h>
#include "basic_types.h"
#include "platform_opts.h"
#include "mmf_sink.h"
#include "sockets.h"
#include "lwip/netif.h"
#include "mp4_encap.h"
#define AUDIO_SIZE 1024*10
#define VIDEO_SIZE 1024*10
#define MOOV_BOX_SIZE 1024*64
#define H264_BUF_SIZE 1024*224//must 32 kb multiple
SDRAM_DATA_SECTION unsigned char moov_box_[MOOV_BOX_SIZE];
SDRAM_DATA_SECTION int video_buffer_index[VIDEO_SIZE];
SDRAM_DATA_SECTION int video_buffer_size[VIDEO_SIZE];
SDRAM_DATA_SECTION int audio_buffer_index[AUDIO_SIZE];
SDRAM_DATA_SECTION int audio_buffer_size[AUDIO_SIZE];
SDRAM_DATA_SECTION unsigned char h264_buffer[H264_BUF_SIZE];
int fatfs_init(void* ctx){
char path[64];
int test_result = 1;
int ret = 0;
pmp4_context mp4_ctx = (pmp4_context)ctx;
//1 init disk drive
DBG_8195A("Init Disk driver.\n");
// Set sdio debug level
DBG_INFO_MSG_OFF(_DBG_SDIO_);
DBG_WARN_MSG_OFF(_DBG_SDIO_);
DBG_ERR_MSG_ON(_DBG_SDIO_);
if(sdio_init_host()!=0){
DBG_8195A("SDIO host init fail.\n");
return -1;
}
//1 register disk driver to fatfs
DBG_8195A("Register disk driver to Fatfs.\n");
mp4_ctx->drv_num = FATFS_RegisterDiskDriver(&SD_disk_Driver);
if(mp4_ctx->drv_num < 0){
DBG_8195A("Rigester disk driver to FATFS fail.\n");
goto fail;
}else{
mp4_ctx->_drv[0] = mp4_ctx->drv_num + '0';
mp4_ctx->_drv[1] = ':';
mp4_ctx->_drv[2] = '/';
mp4_ctx->_drv[3] = 0;
}
DBG_8195A("FatFS Write begin......\n\n");
printf("\r\ndrv(%s)", mp4_ctx->_drv);
if(f_mount(&mp4_ctx->m_fs,mp4_ctx->_drv, 1)!= FR_OK){
DBG_8195A("FATFS mount logical drive fail.\n");
goto fail;
}
return 0;
fail:
sdio_deinit_host();
return -1;
}
int fatfs_close(void *ctx){
pmp4_context mp4_ctx = (pmp4_context)ctx;
if(f_mount(NULL,mp4_ctx->_drv, 1) != FR_OK){
DBG_8195A("FATFS unmount logical drive fail.\n");
}
if(FATFS_UnRegisterDiskDriver(mp4_ctx->drv_num))
DBG_8195A("Unregister disk driver from FATFS fail.\n");
sdio_deinit_host();
return 0;
}
void mp4_mod_close(void* ctx)
{
pmp4_context mp4_ctx = (pmp4_context)ctx;
mp4_muxer_close(mp4_ctx);
fatfs_close(mp4_ctx);
free(mp4_ctx);
}
void* mp4_mod_open(void)
{
pmp4_context mp4_ctx = (pmp4_context)malloc(sizeof(mp4_context));
if(!mp4_ctx){
printf("malloc failed\r\n");
return NULL;
}
memset(mp4_ctx,0,sizeof(mp4_context));
mp4_muxer_init(mp4_ctx);
if(fatfs_init(mp4_ctx)<0){
free(mp4_ctx);
return NULL;
}
set_mp4_audio_buffer(mp4_ctx,audio_buffer_index,audio_buffer_size,AUDIO_SIZE);
set_mp4_video_buffer(mp4_ctx,video_buffer_index,video_buffer_size,VIDEO_SIZE);
set_mp4_moov_buffer(mp4_ctx,moov_box_,MOOV_BOX_SIZE);
set_mp4_write_buffer(mp4_ctx,h264_buffer,H264_BUF_SIZE);
printf("mp4_mod_open\r\n");
return (void*)mp4_ctx;
}
int mp4_mod_set_param(void* ctx, int cmd, int arg)
{
int ret = 0;
pmp4_context mp4_ctx = (pmp4_context)ctx;
switch(cmd){
case CMD_SET_HEIGHT:
mp4_ctx->height=arg;
break;
case CMD_SET_WIDTH:
mp4_ctx->width = arg;
break;
case CMD_SET_FRAMERATE:
mp4_ctx->frame_rate = arg;
break;
case CMD_SET_CHANNEL:
mp4_ctx->channel_count = arg;
break;
case CMD_SET_SAMPLERATE:
mp4_ctx->sample_rate = arg;
break;
case CMD_SET_ST_PERIOD:
mp4_ctx->period_time = arg*1000;
break;
case CMD_SET_ST_TOTAL:
mp4_ctx->file_total = arg;
break;
case CMD_SET_ST_TYPE:
mp4_ctx->type = arg;
break;
case CMD_SET_ST_FILENAME:
memset(mp4_ctx->filename,0,sizeof(mp4_ctx->filename));
strcpy(mp4_ctx->filename,(char*)arg);
break;
case CMD_SET_ST_START:
mp4_set_start_status(mp4_ctx);
break;
default:
ret = EINVAL;
break;
}
return ret;
}
#if 0
int mp4_mod_handle(void* ctx, void* b)
{
pmp4_context mp4_ctx = (pmp4_context)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
int status = 0;
if((exbuf->state == STAT_INIT) || (exbuf->state == STAT_USED))
return -EAGAIN;
if(exbuf->codec_fmt == FMT_A_MP4A_LATM || exbuf->codec_fmt == FMT_V_MP4V_ES){
mp4_handle(mp4_ctx,exbuf->data,exbuf->len,exbuf->codec_fmt);
}
exbuf->state=STAT_USED;
return 0;
}
#endif
int mp4_mod_handle(void* ctx, void* b)
{
pmp4_context mp4_ctx = (pmp4_context)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
int status = 0;
if((exbuf->state == STAT_INIT) || (exbuf->state == STAT_USED))
return -EAGAIN;
if(exbuf->state == STAT_RESERVED){
if(mp4_ctx->buffer_write_status == 0)
exbuf->state=STAT_USED;
return 0;
}
if(exbuf->codec_fmt == FMT_A_MP4A_LATM || exbuf->codec_fmt == FMT_V_MP4V_ES){
mp4_handle(mp4_ctx,exbuf->data,exbuf->len,exbuf->codec_fmt);
}
if((mp4_ctx->buffer_write_status == 1) && (mp4_ctx->iframe == 1) && (exbuf->codec_fmt == FMT_V_MP4V_ES))
exbuf->state=STAT_RESERVED;
else
exbuf->state=STAT_USED;
return 0;
}
msink_module_t mp4_module =
{
.create = mp4_mod_open,
.destroy = mp4_mod_close,
.set_param = mp4_mod_set_param,
.handle = mp4_mod_handle,
};

View file

@ -0,0 +1,215 @@
#include "mmf_sink.h"
//rtsp header files
#include "rtsp/rtsp_api.h"
#include "sockets.h"
#include "lwip/netif.h"
static struct rtp_object rtp_payload;
// to get stream id,
// need mutex to protect this routine? i dont think it is necessary
#define STREAM_FLOW_ID_BASE 0
static u32 stream_flow_id_bitmap = 0;
static _mutex stream_flow_id_bitmap_lock = NULL;
//static u32 rtsp_tick_offset = 0;
//static u32 rtsp_stream_num = 0;
// codec map
//
static int codec_map_v[] = {AV_CODEC_ID_MJPEG, AV_CODEC_ID_H264, AV_CODEC_ID_MP4V_ES};
static int codec_map_a[] = {AV_CODEC_ID_PCMU, AV_CODEC_ID_PCMA, AV_CODEC_ID_MP4A_LATM};
void rtsp_mod_close(void* ctx)
{
struct rtsp_context * rtsp_ctx = (struct rtsp_context *)ctx;
if(rtsp_ctx->stream_ctx[0].codec)
free(rtsp_ctx->stream_ctx[0].codec);
rtsp_close(rtsp_ctx);
rtsp_context_free(rtsp_ctx);
if(stream_flow_id_bitmap_lock != NULL)
rtw_mutex_free(&stream_flow_id_bitmap_lock);
stream_flow_id_bitmap = 0;
}
void* rtsp_mod_open(void)
{
int timeout = 10;
struct rtsp_context *rtsp_ctx = rtsp_context_create(1);
if(!rtsp_ctx) return NULL;
/*open rtsp service task*/
if(rtsp_open(rtsp_ctx)<0){
rtsp_context_free(rtsp_ctx);
rtsp_ctx = NULL;
}
while(!rtsp_is_service_enabled(rtsp_ctx)){
rtw_mdelay_os(1000);
if(timeout--<=0){
printf("\n\rwait rtsp service time out...");
goto rtsp_mod_open_fail;
}
}
// init payload object
rtp_object_init(&rtp_payload);
rtsp_ctx->stream_ctx[0].codec = malloc(sizeof(struct codec_info));
if(!rtsp_ctx->stream_ctx[0].codec)
goto rtsp_mod_open_fail;
//rtsp_clock_init(rtsp_ctx->stream_ctx[0].codec->clock_rate);
//rtsp_tick_offset = rtw_get_current_time();
//rtsp_stream_num = 1;
return (void*)rtsp_ctx;
rtsp_mod_open_fail:
rtp_object_deinit(&rtp_payload);
rtsp_mod_close(rtsp_ctx);
return NULL;
}
int rtsp_mod_set_param(void* ctx, int cmd, int arg)
{
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)ctx;
struct stream_context *stream_ctx = &rtsp_ctx->stream_ctx[0];
int *codec_map = NULL;
switch(cmd){
case CMD_SET_FRAMERATE:
stream_ctx->framerate = arg;
break;
case CMD_SET_BITRATE:
stream_ctx->bitrate = arg;
break;
case CMD_SET_SAMPLERATE:
stream_ctx->samplerate = arg;
break;
case CMD_SET_CHANNEL:
stream_ctx->channel = arg;
break;
// for H264
case CMD_SET_SPS:
set_sps_string((char*)arg);
break;
case CMD_SET_PPS:
set_pps_string((char*)arg);
break;
case CMD_SET_LEVEL:
set_profile_lv_string((char*)arg);
break;
case CMD_SET_APPLY:
if(stream_flow_id_bitmap_lock == NULL)
rtw_mutex_init(&stream_flow_id_bitmap_lock);
if(stream_ctx->stream_id < 0)
stream_ctx->stream_id = rtsp_get_number(STREAM_FLOW_ID_BASE, &stream_flow_id_bitmap, &stream_flow_id_bitmap_lock);
rtp_stream_statistics_sync(stream_ctx);
break;
/*
case CMD_SET_STREAMNUM:
if(arg>1){ // arg = 1, do nothing, because has been created when open
// free original stream
free(stream_ctx);
// malloc new steram and init
rtsp_ctx->nb_streams = arg;
rtsp_ctx->stream_ctx = malloc(arg * sizeof(struct stream_context));
if(!rtsp_ctx->stream_ctx) return -ENOMEM;
for(int i = 0; i < arg; i++)
{
rtsp_ctx->rtpseq[i] = 0;
rtsp_stream_context_init(rtsp_ctx, &rtsp_ctx->stream_ctx[i]);
}
}
break;
*/
case CMD_SET_STREAMMING:
if(arg == ON){
rtsp_clock_init(rtsp_ctx->stream_ctx[0].codec->clock_rate);
rtsp_start(rtsp_ctx);
// insert to input queue
rtp_object_in_stream_queue(&rtp_payload, &rtsp_ctx->stream_ctx[0]);
}else
rtsp_stop(rtsp_ctx);
break;
case CMD_SET_CODEC:
codec_map = ((arg&0xf0)==0x00)?codec_map_v:codec_map_a;
get_codec_by_id(stream_ctx->codec, codec_map[arg&0xf]);
stream_ctx->media_type = rtsp_parse_stream_media_type(stream_ctx->codec);
rtp_load_o_handler_by_codec_id(&rtp_payload, codec_map[arg&0xf]);
if(rtp_payload.rtp_object_handler == NULL)
return -EINVAL;
break;
default:
break;
}
return 0;
}
// private function
int rtsp_mod_wait_complete(void)
{
return 1;
}
// private function
int rtsp_mod_compelete_cb(void)
{
return 1;
}
int rtsp_mod_handle(void* ctx, void* b)
{
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
struct stream_context *stream_ctx = &rtsp_ctx->stream_ctx[0];
struct rtp_object *payload = NULL;//&rtp_payload;
if(exbuf->state != STAT_READY)
return -EAGAIN;
if(rtsp_ctx->state != RTSP_PLAYING)
goto end;
// wait output not empty and get one
// Get payload from rtsp module
do{
payload = rtp_object_out_stream_queue(stream_ctx);
if(payload==NULL) vTaskDelay(1);
}while(payload == NULL);
// insert payload to rtsp_ctx stream
//printf("%d\n\r", xTaskGetTickCount());
/*fill payload*/
payload->index = exbuf->index;
payload->data = exbuf->data;
payload->len = exbuf->len;
payload->timestamp = exbuf->timestamp;
if(payload->timestamp==0)
payload->timestamp = rtsp_get_current_tick();
else
payload->timestamp = exbuf->timestamp;
//printf("ts: %8x\n\r", payload->timestamp);
/* because we will fill&send a complete frame in single rtp object, set both fs & fe to 1 and fd to 0*/
rtp_object_set_fs(payload, 1);
rtp_object_set_fe(payload, 1);
rtp_object_set_fd(payload, 0);
/* set payload state to READY to enable rtp task process this rtp object;*/
payload->state = RTP_OBJECT_READY;
rtp_object_in_stream_queue(payload, stream_ctx);
// TODO: use inter task communication
// wait payload state to IDEL or USED
rtsp_mod_wait_complete();
while(list_empty(&stream_ctx->output_queue))
vTaskDelay(1);
end:
exbuf->state = STAT_USED;
return 0;
}
msink_module_t rtsp_module =
{
.create = rtsp_mod_open,
.destroy = rtsp_mod_close,
.set_param = rtsp_mod_set_param,
.handle = rtsp_mod_handle,
};

View file

@ -0,0 +1,257 @@
#include "mmf_sink.h"
//rtsp header files
#include "rtsp/rtsp_api.h"
#include "sockets.h"
#include "lwip/netif.h"
#define STREAM_FLOW_ID_BASE 0
static u32 stream_flow_id_bitmap = 0;
static _mutex stream_flow_id_bitmap_lock = NULL;
static int channel_idx=0;
//static int *codec_chennel_map; //
//static struct rtp_object *rtp_payload;
static struct __internal_payload{
int codec_id;
struct rtp_object payload;
}*rtpobj = NULL;
//static u32 rtsp_tick_offset = 0;
//static u32 rtsp_stream_num = 0;
// codec map
//
static int codec_map_v[] = {AV_CODEC_ID_MJPEG, AV_CODEC_ID_H264, AV_CODEC_ID_MP4V_ES};
static int codec_map_a[] = {AV_CODEC_ID_PCMU, AV_CODEC_ID_PCMA, AV_CODEC_ID_MP4A_LATM};
void rtsp2_mod_close(void* ctx)
{
struct rtsp_context * rtsp_ctx = (struct rtsp_context *)ctx;
for(int i=0;i<rtsp_ctx->nb_streams;i++){
if(rtsp_ctx->stream_ctx[i].codec)
free(rtsp_ctx->stream_ctx[i].codec);
rtp_object_deinit(&rtpobj[i].payload);
}
if(rtpobj)
free(rtpobj);
rtsp_close(rtsp_ctx);
rtsp_context_free(rtsp_ctx);
if(stream_flow_id_bitmap_lock != NULL)
rtw_mutex_free(&stream_flow_id_bitmap_lock);
stream_flow_id_bitmap = 0;
}
void* rtsp2_mod_open(void)
{
int timeout = 10;
struct rtsp_context *rtsp_ctx = rtsp_context_create(2);
if(!rtsp_ctx) return NULL;
/*open rtsp service task*/
if(rtsp_open(rtsp_ctx)<0){
rtsp_context_free(rtsp_ctx);
rtsp_ctx = NULL;
}
while(!rtsp_is_service_enabled(rtsp_ctx)){
rtw_mdelay_os(1000);
if(timeout--<=0){
printf("\n\rwait rtsp service time out...");
goto rtsp2_mod_open_fail;
}
}
rtpobj = malloc(sizeof(struct __internal_payload)*rtsp_ctx->nb_streams);
if(!rtpobj)
goto rtsp2_mod_open_fail;
// init payload object
for(int i=0;i<rtsp_ctx->nb_streams;i++){
rtp_object_init(&rtpobj[i].payload);
rtsp_ctx->stream_ctx[i].codec = malloc(sizeof(struct codec_info));
if(!rtsp_ctx->stream_ctx[i].codec)
goto rtsp2_mod_open_fail;
//rtsp_clock_init(rtsp_ctx->stream_ctx[i].codec->clock_rate);
}
return (void*)rtsp_ctx;
rtsp2_mod_open_fail:
//rtp_object_deinit(&rtp_payload);
rtsp2_mod_close(rtsp_ctx);
return NULL;
}
// to get stream id,
// need mutex to protect this routine? i dont think it is necessary
int rtsp2_mod_set_param(void* ctx, int cmd, int arg)
{
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)ctx;
struct stream_context *stream_ctx = &rtsp_ctx->stream_ctx[channel_idx];
int *codec_map = NULL;
switch(cmd){
case CMD_SELECT_CHANNEL:
channel_idx = arg;
break;
case CMD_SET_FRAMERATE:
stream_ctx->framerate = arg;
break;
case CMD_SET_BITRATE:
stream_ctx->bitrate = arg;
break;
case CMD_SET_SAMPLERATE:
stream_ctx->samplerate = arg;
break;
case CMD_SET_CHANNEL:
stream_ctx->channel = arg;
break;
// for H264
case CMD_SET_SPS:
set_sps_string((char*)arg);
break;
case CMD_SET_PPS:
set_pps_string((char*)arg);
break;
case CMD_SET_LEVEL:
set_profile_lv_string((char*)arg);
break;
case CMD_SET_APPLY:
if(stream_flow_id_bitmap_lock == NULL)
rtw_mutex_init(&stream_flow_id_bitmap_lock);
if(stream_ctx->stream_id < 0)
stream_ctx->stream_id = rtsp_get_number(STREAM_FLOW_ID_BASE, &stream_flow_id_bitmap, &stream_flow_id_bitmap_lock);
rtp_stream_statistics_sync(stream_ctx);
rtpobj[channel_idx].codec_id = stream_ctx->codec->codec_id;
break;
/*
case CMD_SET_STREAMNUM:
if(arg>1){ // arg = 1, do nothing, because has been created when open
// free original stream
free(stream_ctx);
// malloc new steram and init
rtsp_ctx->nb_streams = arg;
rtsp_ctx->stream_ctx = malloc(arg * sizeof(struct stream_context));
if(!rtsp_ctx->stream_ctx) return -ENOMEM;
for(int i = 0; i < arg; i++)
{
rtsp_ctx->rtpseq[i] = 0;
rtsp_stream_context_init(rtsp_ctx, &rtsp_ctx->stream_ctx[i]);
}
}
break;
*/
case CMD_SET_STREAMMING:
if(arg == ON){
rtsp_clock_init(rtsp_ctx->stream_ctx[channel_idx].codec->clock_rate);
rtsp_start(rtsp_ctx);
// insert to input queue
for(int i=0;i<rtsp_ctx->nb_streams;i++)
rtp_object_in_stream_queue(&rtpobj[i].payload, &rtsp_ctx->stream_ctx[i]);
}else
rtsp_stop(rtsp_ctx);
break;
case CMD_SET_CODEC:
codec_map = ((arg&0xf0)==0x00)?codec_map_v:codec_map_a;
get_codec_by_id(stream_ctx->codec, codec_map[arg&0xf]);
stream_ctx->media_type = rtsp_parse_stream_media_type(stream_ctx->codec);
rtp_load_o_handler_by_codec_id(&rtpobj[channel_idx].payload, codec_map[arg&0xf]);
if(rtpobj[channel_idx].payload.rtp_object_handler == NULL)
return -EINVAL;
break;
case CMD_SET_FLAG:
if(arg == TIME_SYNC_DIS)
time_sync_disable();
else if(arg == TIME_SYNC_EN)
time_sync_enable();
break;
default:
break;
}
return 0;
}
// private function
int rtsp2_mod_wait_complete(void)
{
return 1;
}
// private function
int rtsp2_mod_compelete_cb(void)
{
return 1;
}
int rtsp2_mod_handle(void* ctx, void* b)
{
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
struct stream_context *stream_ctx = NULL;
struct rtp_object *payload = NULL;//&rtp_payload;
if(exbuf->state != STAT_READY)
return -EAGAIN;
// get channel
int *codec_map = ((exbuf->codec_fmt&0xf0)==0x00)?codec_map_v:codec_map_a;
for(int i=0;i<rtsp_ctx->nb_streams;i++){
if(rtpobj[i].codec_id == codec_map[exbuf->codec_fmt&0xf]){
stream_ctx = &rtsp_ctx->stream_ctx[i];
break;
}
}
if(stream_ctx == NULL)
{
exbuf->state = STAT_INIT;
return -EFAULT;
}
if(rtsp_ctx->state != RTSP_PLAYING)
goto end;
// wait output not empty and get one
// Get payload from rtsp module
do{
payload = rtp_object_out_stream_queue(stream_ctx);
if(payload==NULL) vTaskDelay(1);
}while(payload == NULL);
// insert payload to rtsp_ctx stream
//printf("%d\n\r", xTaskGetTickCount());
/*fill payload*/
payload->index = exbuf->index;
payload->data = exbuf->data;
payload->len = exbuf->len;
//payload->timestamp = (rtw_get_current_time()-rtsp_tick_offset)*90;
payload->timestamp = exbuf->timestamp;//rtsp_get_current_tick();
//printf("ts: %8x\n\r", payload->timestamp);
/* because we will fill&send a complete frame in single rtp object, set both fs & fe to 1 and fd to 0*/
rtp_object_set_fs(payload, 1);
rtp_object_set_fe(payload, 1);
rtp_object_set_fd(payload, 0);
/* set payload state to READY to enable rtp task process this rtp object;*/
payload->state = RTP_OBJECT_READY;
rtp_object_in_stream_queue(payload, stream_ctx);
// TODO: use inter task communication
// wait payload state to IDEL or USED
rtsp2_mod_wait_complete();
while(list_empty(&stream_ctx->output_queue))
vTaskDelay(1);
end:
exbuf->state = STAT_USED;
return 0;
}
msink_module_t rtsp2_module =
{
.create = rtsp2_mod_open,
.destroy = rtsp2_mod_close,
.set_param = rtsp2_mod_set_param,
.handle = rtsp2_mod_handle,
};