a plan for fun

本项目旨在基于mini2440开发板和USB摄像头实现视频的编解码及网络传输。具体包括u-boot和2.6内核移植、摄像头驱动开发、编解码器编写及UI界面设计。

近期由于忙于工作,疲于修改各种bug,自己想做个项目的想法一直搁浅,一方面是因为平日下班回去不想再学了,另外一方面也不知道该给自己制定一个怎样的项目计划。
这段时间工作对个人还是有很大帮助的,对于公司整个系统的构架也熟悉了,所以就打算以公司的项目为基础,指定一个自己的实践项目,名为《平庸版无限视频网络传输》。
===================================================
硬件:mini2440开发板,USB摄像头
软件:bootloader 移植最新的u-boot到mini2440开发板上
     linux 移植2.6内核
     drive 支持相关硬件
     trans & coder & uncoder 编解码以及传输软件
     UI    提供本地显示视频以及windows PC 显示软件
===================================================
时间计划

bootloader: 1 month, 包括支持网络下载等功能

linux: 2 weeks

dirive: 2 weeks 主要是摄像头驱动的移植

trans & coder & uncolder: 编解码器的编写

UI:1 month, 本地显示 和 客户端显示
====================================================

/****************************************************************************** * Copyright (c) 2018-2020 TP-Link Systems Inc. * * 文件名称: record_plan.c * 版 本: 1.0 * 摘 要: record_plan源文件 * 作 者: Deng Peng<dengpeng@tp-link.com.cn> * 创建时间: 2019-2-22 ******************************************************************************/ #include <nvmp_utils.h> #include <error.h> #include <unistd.h> #include "slp_model.h" #include "libds.h" #include "record_plan.h" #define DAY_LAST_MINUTES (24 * 60) LOCAL S32 s_timer_id = -1; /* 定时器id */ /* 当前录像计划类型 */ static REC_TYPE_E rec_plan_type = REC_TYPE_MAX; void rec_plan_timer_fun(S32 param); /* 定时器到期调用函数 */ /* 向录像模块发送录像动作 */ /* 注意这里type的枚举值是REC_TYPE_E,不是REC_PLAN_TYPE_E */ S32 notify_outer_module(REC_TYPE_E type) { REC_ACTION rec_action; S32 ret = ERROR; if (type < REC_TYPE_NULL || type >= REC_TYPE_MAX) { RECORD_ERROR("invalid rec_type"); return ERROR; } rec_action.rec_type = type; ret = msg_send(REC_PLAN_ACTION_CHANGED,(U8 *) &rec_action, sizeof(REC_ACTION)); RECORD_DEBUG("REC_TYPE_E type[%d], return %d", type, ret); return ret; } /****************************************************************************** * 函数名称: do_rec_plan() * 函数描述: 执行录像计划, 若当前时间在录像时间段内,则向录像模块发送dms消息(告知:录像类型,录像/停止录像) 并设置定时器到下次启动时间再次调用本函数 * 输 出: N/A * 返 回 值: ERROR/OK * 备 注: 目前只处理当天内的录像计划,若当天没有计划,则定时到当天的最后一秒再次调用本函数 ******************************************************************************/ static S32 do_rec_plan() { int i; S32 ret = OK; PTR_REC_PLAN ptr_rec_plan = NULL; PTR_REC_PLAN_SECTION p_rec_plan_section = NULL; time_t now; struct tm *tm_now; int now_minute; WEEK_DAY wday = 0; S32 next_start_seconds; S32 next_start_minute; ptr_rec_plan = get_rec_plan_cfg(); if (ptr_rec_plan == NULL) { RECORD_ERROR("get_rec_plan_cfg failed"); ret = ERROR; goto end; } /* 如果“SD卡录像”选项关闭,则发送一个停止录像消息,然后返回 */ if (FALSE == ptr_rec_plan->b_enable) { rec_plan_type = REC_TYPE_NULL; notify_outer_module(REC_TYPE_NULL); return OK; } now = time(NULL); tm_now = localtime(&now); now_minute = tm_now->tm_hour * 60 + tm_now->tm_min; /* 查找当前时间所在的录像计划时间段 */ wday = (tm_now->tm_wday + 6) % 7; /* tm_wday: 0-sunday, 1-monday,而录像计划数组的顺序为0-MONDAY,1-Tuesday,...*/ p_rec_plan_section = (PTR_REC_PLAN_SECTION) &(ptr_rec_plan->week_rec_plan->plan_section[wday * MAX_SECTION_PER_DAY]); for (i = 0; i < MAX_SECTION_PER_DAY; i++) { RECORD_DEBUG("section[%d] type[%u] sm[%u] em[%u]", i, p_rec_plan_section[i].type, p_rec_plan_section[i].start_minute, p_rec_plan_section[i].end_minute); if (p_rec_plan_section[i].type == REC_PLAN_TYPE_NULL) { continue; } /* 找到了当前时间所在的录像计划的时间段,依次做3件事: * 1、计算本次录像时段的剩余时间-next_start_seconds * 2、根据录像类型向录像模块发送消息 * 3、设置定时器,next_start_seconds后再次调用本函数*/ if ((p_rec_plan_section[i].start_minute <= now_minute) && (p_rec_plan_section[i].end_minute > now_minute)) { RECORD_DEBUG("section:%d start_minute:%d end_minute:%d now:%d", i, p_rec_plan_section[i].start_minute, p_rec_plan_section[i].end_minute, now_minute); /* 计算距离本时间段结束的时间,单位(秒) */ next_start_seconds = (p_rec_plan_section[i].end_minute - now_minute - 1) * 60 + (60 - tm_now->tm_sec); switch (p_rec_plan_section[i].type) { case REC_PLAN_TYPE_EVENT: rec_plan_type = REC_TYPE_MOTION; /* 通知storage模块当前处于移动侦测录像计划;是否有移动侦测事件发生由storage自行判断 */ notify_outer_module(REC_TYPE_MOTION); break; case REC_PLAN_TYPE_TIME: rec_plan_type = REC_TYPE_TIME; /* 向录像模块发送 定时录像指令 */ notify_outer_module(REC_TYPE_TIME); break; default: rec_plan_type = REC_TYPE_NULL; /* 既不是移动侦测录像,也不是定时录像,则表明发生了错误 */ RECORD_ERROR("do_rec_plan: [%d-%d] invalid record type [%u]", p_rec_plan_section[i].start_minute, p_rec_plan_section[i].end_minute, p_rec_plan_section[i].type); return ERROR; } goto start_timer; } } /* 当前时间不在录像时间段内,发送停止录像的消息 */ rec_plan_type = REC_TYPE_NULL; notify_outer_module(REC_TYPE_NULL); /* 查找最近的录像计划时间段的开始时间 */ next_start_minute = DAY_LAST_MINUTES; for (i = 0; i < MAX_SECTION_PER_DAY; i++) { if (p_rec_plan_section[i].type != REC_PLAN_TYPE_NULL) { if ((p_rec_plan_section[i].start_minute > now_minute) && (p_rec_plan_section[i].start_minute < next_start_minute)) { next_start_minute = p_rec_plan_section[i].start_minute; } } } /* 计算距离下一次录像时段开始时间的秒数 */ next_start_seconds = (next_start_minute - now_minute - 1) * 60 + 60 - tm_now->tm_sec; start_timer: s_timer_id = inet_add_timer(rec_plan_timer_fun, 0, next_start_seconds, EXECUTE_SINGLE); if (ERROR == s_timer_id) { RECORD_ERROR("inet_add_timer return ERROR"); } end: return ret; } void rec_plan_timer_fun(S32 param) { do_rec_plan(); } /* 系统时间更新消息的回调函数 */ S32 ntp_time_reload_cb(void *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { TIME_CALIBRATION *time_cali = NULL; if (mbuf == NULL || mlen != sizeof(TIME_CALIBRATION)) { return ERROR; } time_cali = (TIME_CALIBRATION *)mbuf; /* 校时失败什么都不做 */ if (time_cali->status != TIME_CALIBRATION_SUCC) { return OK; } /* 删除系统时间更新前设置的定时器 */ if (ERROR != s_timer_id) { inet_del_timer(s_timer_id); s_timer_id = ERROR; } /* 系统时间更新后,立即执行一次录像计划 */ return do_rec_plan(); } /***************************************************** * 下面是本模块作为cap子模块的配套函数 *****************************************************/ LOCAL S32 record_plan_init() { S32 ret = OK; /* 初始化录像计划结构体 */ ret = rec_plan_init(); if (ERROR == ret) { RECORD_INFO("rec_plan_init fail"); return ret; } /* 关注系统时间更新消息 */ ret = msg_attach_handler(TIME_CALIBRATION_MSG_ID, ntp_time_reload_cb); if (ERROR == ret) { RECORD_INFO("msg_attach_handler fail"); return ret; } RECORD_INFO("init over, ret[%d]", ret); return ret; } LOCAL S32 record_plan_start() { S32 ret = ERROR; /* 读取本机上的录像计划配置表 */ ret = load_record_plan_cfg(); if (ERROR == ret) { RECORD_ERROR("load_record_plan_cfg error."); return SLP_EGENERIC; } /* 如果尚未开启定时器,那么立即执行一次录像计划 */ if (ERROR == s_timer_id) { ret = do_rec_plan(); if (ERROR == ret) { RECORD_ERROR("load_record_plan_cfg error."); return SLP_EGENERIC; } } RECORD_INFO("start over, ret[%d]", ret); return ret; } S32 record_plan_reload() { S32 ret = OK; /* 读取新的录像计划配置表 */ ret = load_record_plan_cfg(); if (ERROR == ret) { RECORD_ERROR("load_record_plan_cfg error."); return SLP_EGENERIC; } /* 更新录像计划配置表后,删除先前的定时器,然后执行一次录像计划 */ if (ERROR != s_timer_id) { inet_del_timer(s_timer_id); s_timer_id = ERROR; } ret = do_rec_plan(); if (ERROR == ret) { RECORD_ERROR("load_record_plan_cfg error."); return SLP_EGENERIC; } RECORD_INFO("reload over, ret[%d]", ret); return SLP_ENONE; } LOCAL S32 record_plan_stop() { msg_detach_handler(TIME_CALIBRATION_MSG_ID, ntp_time_reload_cb); if (ERROR != s_timer_id) { inet_del_timer(s_timer_id); s_timer_id = ERROR; } RECORD_INFO("record plan stop over."); return SLP_ENONE; } #define WEEK_PATH_SUFFIX_SIZE 5 /* listConfig路径后缀最大长度为4,加上\0占5字节 例如:_168 */ LOCAL S32 record_plan_check(BIN_AREA *bin_area) { REC_PLAN_SECTION plan_section; char record_path_str[sizeof(REC_PLAN_WEEK_PATH) + WEEK_PATH_SUFFIX_SIZE] = {0}; S32 section_count = 0; for (section_count = 0; section_count < WEEK_PLAN_LIST_SIZE; ++section_count) { memset(&plan_section, 0, sizeof(REC_PLAN_SECTION)); snprintf(record_path_str, sizeof(record_path_str), "%s_%d", REC_PLAN_WEEK_PATH, section_count + 1); if (0 != ds_ext_read(bin_area, record_path_str, (U8 *)&plan_section, sizeof(REC_PLAN_SECTION))) { if (plan_section.start_minute > 1440 || plan_section.end_minute > 1440) { return SLP_EINVARG; } } } return SLP_ENONE; } LOCAL void record_plan_main() { /*************************************************************************************/ /********* Desc of /record_plan/chn1_channel *********************************************/ /*************************************************************************************/ DS_OPT_DESC chn1_channel_options[] = { DS_SWITCH_OPT(REC_PLAN_ENABLE, enabled, OPT_FLAG_NORM), }; DS_SEG_DESC chn1_channel_segments[] = { DS_STRUCT_SEG("chn1_channel", SEG_LIM_RW, SEG_GROUP_ROOT, REC_PLAN_ENABLE, chn1_channel_options), }; DS_SECT_DESC chn1_channel_sections[] = { DS_STRUCT_SECT("chn1_channel", chn1_channel_segments), }; /*************************************************************************************/ /********* Desc of /record_plan/chn1_channel *********************************************/ /*************************************************************************************/ DS_OPT_DESC week_plan_options[] = { DS_U8_OPT(REC_PLAN_SECTION, type, OPT_FLAG_NORM), DS_U16_OPT(REC_PLAN_SECTION, start_minute, OPT_FLAG_NORM), DS_U16_OPT(REC_PLAN_SECTION, end_minute, OPT_FLAG_NORM), }; DS_SEG_DESC week_plan_segments[] = { DS_STRUCT_SEG("week_plan", SEG_LIM_RW, SEG_GROUP_ROOT, REC_PLAN_SECTION, week_plan_options), }; DS_TBL_DESC record_plan_tables[] = { DS_STRUCT_TBL("chn1_channel", TBL_ATTR_CFG, chn1_channel_sections), DSLL_TBL("week_plan", TBL_ATTR_LSTCFG, TABLE_FLAG_PREALLOCATE, WEEK_PLAN_LIST_SIZE, segment, week_plan_segments, NELEMENTS(week_plan_segments)) }; DS_DAT_MON_DESC record_plan_data_monitor[] = { DS_DAT_MON(REC_PLAN_ENABLE_PATH, DATA_ATTRI_CHECK), DS_DAT_MON(REC_PLAN_WEEK_PATH, DATA_ATTRI_CHECK), }; DS_MOD_DESC record_plan_module = DS_STRUCT_MOD("record_plan", record_plan_init, record_plan_check, NULL, record_plan_start, record_plan_stop, record_plan_tables, record_plan_data_monitor); MODULE *module_node = ds_register_module("record_plan", &record_plan_module); CAP_ASSERT(NULL != module_node); } CAP_INIT(record_plan_main); 详细解析一下
最新发布
08-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值