Iot SDK 4.0.0
载入中...
搜索中...
未找到
Unisoc_UMS9117 平台集成说明

本文是 Juphoon RTOS RTC SDK 包的一部分。主要目标是帮助集成人员
了解基本流程,可以快速的集成并验证音视频功能。

  1. release_note.txt 版本的发布说明和历史记录
  2. C 语言头文件:
    • jrtc.h 应用层接口头文件,函数原型和详细的注释说明
    • jrtc0.h 较低层高级接口,可定制化的部分参数和对应的注释说明
  3. C 静态库 libjrtc.a 所在目录:
    • libs/ums9117_240X320BAR_48MB_CAT1 UMS9117 的正式版库
  4. readme.md 该 SDK 说明文档

因为音视频功能依赖硬件支持, 所以 **不提供模拟器版本的库**。

一对一语音呼叫 Juphoon Cloud 终端

  1. 配置全局环境
    /* 配置参数:
    - AppKey 是应用在菊风云平台中的唯一标识,类似应用的身份证.
    必须通过在平台创建应用获取, 请参考如下文档:
    https://developer.juphoon.com/cn/juphoon_platform/03_console_description/03_app_management.html
    - UID 是设备在菊风云平台的账号,类似设备的身份证.
    自定义后, 必须在平台导入该账号, 请参考如下文档:
    https://developer.juphoon.com/cn/cat_1/01_import_iot_account.html
    - Key 是设备在通讯时的对称秘钥, 用于增强安全.
    必须在从平台获取或导入, 请参考如下文档:
    https://developer.juphoon.com/cn/cat_1/00_get_secret_key.html
    */
    jrtc_config (AppKey, UID, Key, "");
    void jrtc_config(const char appKey[24], const char license[64], const char aesKey[16], const char tokens[128], const struct jrtc_handler_t *handler)
    全局配置, 只需调用一次, 内部将复制所有参数
  2. 呼叫 Juphoon Cloud 终端
    /* 打开通话 */
    struct jrtc_t* jc = jrtc_open (对方账号, "", NULL, NULL);
    /* 开启音频发送 */
    void jrtc_activate(struct jrtc_t *jc, int devices)
    开启发送状态.
    struct jrtc_t * jrtc_open(const char channelId[64], const char uid[64], struct jrtc_image_t *video, struct jrtc_image_t *camera, struct jrtc_options_t *options)
    分配通话资源并启动网络线程.
    @ JRTC_AUDIO
    定义 jrtc.h:589

一对一视频呼叫 Juphoon Cloud 终端

  1. 呼叫 Juphoon Cloud 终端
    /* 配置环境, 请参考上面的'一对一语音呼叫' */
    jrtc_config (AppKey, UID, Key, "");
    /* width 和 height 设置值随硬件而异,一般要求必须是8的倍数;镜头采集的固定输出为240*240.
    - 图像需旋转90度, 所以height x width 也不能大于屏幕尺寸.
    - 内部 JPG 编码, 所以kbps不启作用, 只须 > 0
    - fps 可以控制最大帧速
    */
    static struct jrtc_image_t _video, _camera;
    _video.width = _camera.width = 176;
    _video.height = _camera.height = 176;
    _video.fps = _camera.fps = 10;
    _video.kbps = _camera.kbps = 120;
    struct jrtc_t* jc = jrtc_open (对方账号, "", &_video, &_camera);
    jrtc_activate(jc, JRTC_AUDIO|JRTC_CAMERA); /*< 开启音频和镜头的发送 */
    @ JRTC_CAMERA
    定义 jrtc.h:588
    视频流中的图像
    定义 jrtc.h:179
    unsigned short width
    图像宽
    定义 jrtc.h:182
  2. 创建定时器并激活
    SCI_TIMER_PTR* timer = SCI_CreatePeriodTimer("render", OnTimer, (uint32)0, 40, 0);
    SCI_ActiveTimer(timer);
  3. 在定时回调函数中,绘制视频图像
    static void OnTimer(uint32 p) {
    struct jrtc_image_t* img = &_video;
    if (img->get != img->put) {
    lcd_show(img); /*< 显示图像*/
    img->get = img->put; /*< 复位读计数 */
    }
    }
    static void lcd_show(struct jrtc_image_t*image) {
    unsigned short lcd_width = image->width, lcd_height = image->height;
    BLOCKCFG_T cfg;
    uint8 *rgb_addr, *y_addr, *uv_addr;
    if (image->format == 2)
    {
    y_addr = image->data;
    uv_addr = (uint8 *)image->data + lcd_width * lcd_height;
    }
    else
    rgb_addr = image->data;
    SCI_TRACE_LOW("%s %d %d", __FUNCTION__, image->width, image->height);
    LCD_GetLcdCtrlSemaphore(MAIN_LCD_ID);
    {
    cfg.start_x = 0;
    cfg.start_y = 0;
    cfg.end_x = lcd_width + cfg.start_x - 1;
    cfg.end_y = lcd_height + cfg.start_y - 1;
    if (image->format == 2)
    cfg.resolution = LCD_RESOLUTION_YUV422;
    else
    cfg.resolution = LCD_RESOLUTION_RGB565;
    cfg.width = lcd_width;
    cfg.colorkey_en = FALSE;
    cfg.alpha_sel = 1;
    cfg.alpha = 0xFF;
    cfg.priority = 0;
    cfg.type = 1; //0:OSD; 1:image
    cfg.rotation = 0;
    cfg.endian_switch = 2;
    cfg.set_endian_flag = 1;
    cfg.rb_switch = 0;
    LCD_EnterSleep(MAIN_LCD_ID, FALSE);
    if (image->format == 2)
    {
    LCD_SetBlockBuffer(MAIN_LCD_ID, 0, (uint32*)y_addr);
    LCD_SetUVBuffer(MAIN_LCD_ID, 0, (uint32*)uv_addr);
    }
    else
    LCD_SetBlockBuffer(MAIN_LCD_ID, 0, (uint32*)rgb_addr);
    LCD_ConfigBlock(MAIN_LCD_ID, 0, cfg);
    LCD_EnableBlock(MAIN_LCD_ID, 0);
    LCD_InvalidateRect(0, cfg.start_x, cfg.start_y, cfg.end_x, cfg.end_y);
    }
    LCD_PutLcdCtrlSemaphore(MAIN_LCD_ID);
    }
    char format
    jrtc_dtype 数据格式
    定义 jrtc.h:184
    void * data
    图像数据
    定义 jrtc.h:180
    volatile char put
    内部使用, 标识图像已更新
    定义 jrtc.h:188
    volatile char get
    外部使用, 标识界面已绘制
    定义 jrtc.h:189
    unsigned short height
    图像高
    定义 jrtc.h:183
  4. UMS9117平台可能出现定时器内渲染耗时导致的崩溃,可尝试渲染另起线程,起定时器发同步消息给渲染线程的方式
    taskid = SCI_CREATE_THREAD("render", "jc-task-test", OnRender, 1, 0, 1024, 20, 227, SCI_PREEMPT, SCI_DONT_START);
    SCI_ResumeThread(taskid);
    sig_ptr = (RENDER_SIG_T *)malloc(sizeof(RENDER_SIG_T));
    static void OnTimer(uint32 p)
    {
    sig_ptr->command = 222;
    sig_ptr->data = p;
    SCI_TRACE_LOW("render taskid=%d", taskid);
    if (SCI_SUCCESS != SCI_SendSignal((xSignalHeader)sig_ptr, taskid)) {
    SCI_TRACE_LOW("sendsignal failed");
    }
    }
    static void OnRender(void* param)
    {
    RENDER_SIG_T *sig_ptr_t = SCI_NULL;
    JRTC_APPLET_T* applet_ptr = SCI_NULL;
    jrtc_test_t* test = SCI_NULL;
    struct jrtc_image_t* image;
    SCI_TRACE_LOW("onRender");
    while (1) {
    sig_ptr_t = (RENDER_SIG_T *)SCI_GetSignal(taskid);
    if (sig_ptr_t == SCI_NULL)
    continue;
    applet_ptr = (jrtc_test_t*)(sig_ptr_t->data);
    test = &(applet_ptr->test);
    switch (sig_ptr_t->command)
    {
    case 222:
    {
    SCI_TRACE_LOW("match command");
    if (test->testptr) {
    const int state = jrtc_state(test->testptr);
    if (applet_ptr->client_state != state) {
    applet_ptr->client_state = state;
    MMK_PostMsg(applet_ptr->win_handle, MSG_FULL_PAINT, 0, 0);
    }
    if (state < JRTC_JOINED) continue;
    if (test->swap_to_video && test->show_preview && state == JRTC_TALKING)
    {//主叫在接通后,自动切换为视频
    test->show_preview = test->swap_to_video = 0;
    }
    }
    image = test->show_preview ? &test->txframe : &test->rxframe;
    if (image->get != image->put) {
    lcd_show(image);
    image->get = image->put;
    }
    }break;
    default:
    SCI_TRACE_LOW("no match command");
    break;
    }
    }
    }
    jrtc_state
    通话状态
    定义 jrtc.h:411
    @ JRTC_TALKING
    收到媒体后的状态
    定义 jrtc.h:417
    @ JRTC_JOINED
    成功加入会话, 将打开音视频设备
    定义 jrtc.h:416

Unisoc(展锐)Mocor 平台必须的 PDP 流程

Mocor 平台上,创建 socket 需要一个整型值。
因此使用 jrtc_open 前必须对 _jrtc_net_id 赋值,它在 jrtc.h 中声明

extern unsigned _jrtc_net_id;
unsigned _jrtc_net_id
展锐 Mocor 平台 需要设置PDP流程后获得的网络 ID

该值可以由 PDP 流程返回。简单的 PDP 代码流程,如下所示:

  1. 实现 PDP 流程的回调函数
    static void lwm2m_socket_Handle_PdpMsg(MMIPDP_CNF_INFO_T *msg_ptr) {
    int simindex = 0;
    SCI_TRACE_LOW("[lwm2m socket demo debug ------------>]%s %d\n", __FUNCTION__, __LINE__);
    if (PNULL == msg_ptr) {
    SCI_TRACE_LOW("[lwm2m socket demo error]%s %d\n", __FUNCTION__, __LINE__);
    return;
    }
    SCI_TRACE_LOW("[lwm2m socket demo debug]msg_ptr->msg_id = %d.", msg_ptr->msg_id);
    if (msg_ptr->app_handler != MMI_MODULE_SAMPLE) {
    SCI_TRACE_LOW("[lwm2m socket demo error]%s %d\n", __FUNCTION__, __LINE__);
    return;
    }
    switch (msg_ptr->msg_id) {
    /*Physical link established successfully we get IP/DSN ip by nsapi. */
    case MMIPDP_ACTIVE_CNF:
    if (MMIPDP_RESULT_SUCC == msg_ptr->result) {
    _jrtc_net_id = msg_ptr->nsapi;
    SCI_TRACE_LOW("[lwm2m pdp active success, nsapi = %d]%s %d\n", msg_ptr->nsapi, __FUNCTION__, __LINE__);
    }
    else {
    MMIAPIPDP_Deactive(MMI_MODULE_SAMPLE);
    }
    break;
    case MMIPDP_DEACTIVE_CNF:
    SCI_TRACE_LOW("[lwm2m socket demo debug deactive ok]%s %d\n", __FUNCTION__, __LINE__);
    break;
    case MMIPDP_DEACTIVE_IND:
    SCI_TRACE_LOW("[lwm2m socket demo debug start deactive]%s %d\n", __FUNCTION__, __LINE__);
    //MMIAPIPDP_Deactive(THIS_APP_MODULE_ID);
    break;
    default:
    break;
    }
    SCI_TRACE_LOW("[lwm2m socket demo debug <------------]%s %d\n", __FUNCTION__, __LINE__);
    }
  2. 激活 PDP 流程
    int result = -1;
    MMIPDP_ACTIVE_INFO_T active_info = { 0 };
    char* apn_str = PNULL;
    MMICONNECTION_LINKSETTING_DETAIL_T* linksetting = PNULL;
    uint8 linkNum = MMIAPICONNECTION_GetLinkSettingNum(SIM_ID);
    for (int i = 0; i < linkNum; i++) {
    linksetting = PNULL;
    linksetting = MMIAPICONNECTION_GetLinkSettingItemByIndex(SIM_ID, i);
    if (PNULL != linksetting && 0 != linksetting->apn_len) {
    apn_str = (char*)linksetting->apn;
    if (PNULL != apn_str) break;
    }
    }
    active_info.app_handler = MMI_MODULE_SAMPLE;
    active_info.dual_sys = SIM_ID;
    active_info.apn_ptr = apn_str;
    active_info.user_name_ptr = NULL;
    active_info.psw_ptr = NULL;
    active_info.priority = 1;
    active_info.ps_service_rat = MN_UNSPECIFIED;
    active_info.ps_interface = MMIPDP_INTERFACE_GPRS;
    active_info.handle_msg_callback = lwm2m_socket_Handle_PdpMsg;
    active_info.ps_service_type = BROWSER_E;
    active_info.storage = MN_GPRS_STORAGE_ALL;
    MMIAPIPDP_Active(&active_info);

编译说明

因为各平台的编译系统完全不同,所以最好 **根据实际情况灵活实现**。
C 语言头文件可以直接放在当前集成代码所在目录。
C 静态库 libjrtc.a 则按各平台的默认情况举例如下:

  1. 将 libjrtc.a 放在 lib 目录
  2. UMS9117.modules 中添加
    LINKLIBLIST += lib/libjrtc.a