Ejemplo n.º 1
0
 public function create()
 {
     #####节点权限认证需要将节点数据放在nodes=>标志=>节点id=>节点所有父级节点
     if ($this->user['group_type'] > MAX_ADMIN_TYPE && $this->input['node_id']) {
         $sql = 'SELECT id, parents FROM ' . DB_PREFIX . 'channel_node WHERE id IN(' . $this->input['node_id'] . ')';
         $query = $this->db->query($sql);
         while ($row = $this->db->fetch_array($query)) {
             $nodes['nodes'][$row['id']] = $row['parents'];
         }
     }
     $nodes['column_id'] = $this->input['column_id'];
     $nodes['published_column_id'] = '';
     $this->verify_content_prms($nodes);
     #####节点权限认证需要将节点数据放在nodes=>标志=>节点id=>节点所有父级节点
     $name = trim($this->input['name']);
     $code = trim($this->input['code']);
     $server_id = intval($this->input['server_id']);
     //$main_stream_name 	= $this->input['main_stream_name'];
     $stream_name = $this->input['stream_name'];
     $url = $this->input['url'];
     $bitrate = $this->input['bitrate'];
     $is_control = intval($this->input['is_control']);
     //$is_mobile_phone	= intval($this->input['is_mobile_phone']);
     $is_audio = intval($this->input['is_audio']);
     $is_push = intval($this->input['is_push']);
     //$drm				= intval($this->input['drm']);
     $time_shift = intval($this->input['time_shift']);
     //$delay				= intval($this->input['delay']);
     //$record_time_diff	= intval($this->input['record_time_diff']);
     $is_default = intval($this->input['is_default']);
     //$mobile_default	= intval($this->input['mobile_default']);
     //$column_id 			= trim($this->input['column_id']);
     $_appid = $this->input['_appid'];
     $_appname = $this->input['_appname'];
     if (!$name) {
         $this->errorOutput('频道名称不能为空');
     }
     if (!$code) {
         $this->errorOutput('台号不能为空');
     }
     if (!hg_check_string($code)) {
         $this->errorOutput('台号只能包含字母数字');
     }
     $ret_code = $this->mChannel->check_channel_code($code);
     if (!empty($ret_code)) {
         $this->errorOutput('[' . $code . '] 台号已存在!');
     }
     //录制时间
     /*
     if ($time_shift > $this->settings['max_time_shift'])
     {
     	$time_shift = $this->settings['max_time_shift'];
     }
     
     //延时时间
     if ($delay > $this->settings['max_delay'])
     {
     	$delay = $this->settings['max_delay'];
     }
     */
     $channel_stream = array();
     $core_count = count($stream_name);
     for ($i = 0; $i < $core_count; $i++) {
         if (!trim($stream_name[$i])) {
             $this->errorOutput('输出标识不能为空');
         }
         if ($i > 0 && $stream_name[0] == $stream_name[$i]) {
             $this->errorOutput('输出标识不能重复');
         }
         if (!hg_check_string($stream_name[$i])) {
             $this->errorOutput('输出标识只能包含字母数字');
         }
         if (!trim($url[$i])) {
             $this->errorOutput('信号流地址不能为空');
         }
         if (!intval($bitrate[$i])) {
             $this->errorOutput('码流不可以为空');
         }
         $channel_stream[$i] = array('stream_name' => $stream_name[$i], 'url' => $url[$i], 'bitrate' => $bitrate[$i], 'is_main' => $is_default == $i ? 1 : 0, 'order_id' => $i);
     }
     //$main_stream_name = $main_stream_name ? $main_stream_name : $stream_name[0];
     $main_stream_name = $stream_name[$is_default];
     $main_stream_url = $url[$is_default];
     $stream_count = $core_count;
     $level = 1;
     /*
     $level = 1;
     
     if ($delay)
     {
     	$stream_count = $stream_count + $core_count;
     	$level = $level + 1;
     }
     
     if ($is_control)
     {
     	$stream_count = $stream_count + $core_count;
     	$level = $level + 1;
     }
     
     if ($delay || $is_control)
     {
     	$stream_count = $stream_count + $core_count;
     	$level = $level + 1;
     }
     */
     $server_info = $this->mServerConfig->get_server_config_by_id($server_id);
     if (empty($server_info)) {
         $this->errorOutput('该直播服务器不存在或已被删除');
     }
     $type = $server_info['type'] ? $server_info['type'] : 'wowza';
     //$super_token = $server_info['super_token'];
     //服务器状态
     if (!$server_info['status']) {
         $this->errorOutput('该服务器未审核');
     }
     //服务器最大信号数目
     $counts = $server_info['counts'] ? $server_info['counts'] : $this->settings['wowza']['counts'];
     //已用信号数目
     //$_stream_count = $this->mChannel->get_stream_count($server_id, $id);
     $_stream_count = $this->mChannel->get_stream_count($server_id);
     //剩余信号数目
     $over_count = $counts - ($_stream_count + $stream_count);
     if ($over_count < 0) {
         $this->errorOutput('信号数目已超过该服务器数目限制, 已超出 ' . abs($over_count) . ' 条');
     }
     /*
     $server_info = $this->mChannel->get_server_info($server_info);
     
     
     
     $host			= $server_info['host'];
     $input_dir  	= $server_info['input_dir'];
     $output_dir 	= $server_info['output_dir'];
     $wowzaip_input 	= $server_info['wowzaip_input'];
     
     $live_host		= $server_info['live_host'];
     $record_host	= $server_info['record_host'];
     
     $is_live 	= $live_host ? 1 : 0;
     $is_record 	= $record_host ? 1 : 0;
     
     
     //检测流媒体服务器是否正常
     $function = 'media_server_' . $type;
     //如果type是nginx则返回true
     $ret_media_server = $this->$function($server_info, $super_token);
     
     
     if (!$ret_media_server['core_server'])
     {
     	$this->errorOutput($type . '主控服务器未启动');
     }
     
     if ($live_host && !$ret_media_server['live_server'])
     {
     	$this->errorOutput($type . '直播服务器未启动');
     }
     
     if ($record_host && !$ret_media_server['record_server'])
     {
     	$this->errorOutput($type . '录制服务器未启动');
     }
     
     if ($type == 'wowza')
     {
     	$applicationType = 1;
     	if ($is_mobile_phone)
     	{
     		$applicationType = 3;
     	}
     	
     	$application_data = array(
     		'action'	=> 'insert',
     		'id'		=> 0,
     		'name'		=> $code,
     		'length'	=> $time_shift * 3600,
     		'drm'		=> $drm,
     		'type'		=> $applicationType,
     	);
     	
     	$ret_application = $this->mLivemms->outputApplicationOperate($host, $output_dir, $application_data);
     
     	
     	
     	if (!$ret_application['result'])
     	{
     		$this->errorOutput('主控输出层应用创建失败');
     	}
     	
     	$applicationId = intval($ret_application['application']['id']);
     	
     	//直播
     	if ($live_host)
     	{
     		$application_data['id'] 	= $applicationId;
     		$application_data['length'] = 0;
     		$ret_application = $this->mLivemms->outputApplicationOperate($live_host, $output_dir, $application_data);
     		
     		if (!$ret_application['result'])
     		{
     			$this->errorOutput('直播输出层应用创建失败');
     		}
     	}
     	
     	//录制
     	if ($record_host)
     	{
     		$application_data['id'] 	= $applicationId;
     		$application_data['length'] = 0;
     		$ret_application = $this->mLivemms->outputApplicationOperate($record_host, $output_dir, $application_data);
     		
     		if (!$ret_application['result'])
     		{
     			$this->errorOutput('录制输出层应用创建失败');
     		}
     	}
     }
     
     $ret_input_id = $ret_delay_id = $ret_change_id = $ret_output_id = $channel_stream = array();
     $ret_live_output_id = $ret_record_output_id = array();
     
     
     $main_stream_url = '';
     foreach ($stream_name AS $k => $v)
     {
     	$_channel_stream = array(
     		'url'				=> $url[$k],
     		'delay'				=> $delay,
     		'is_control'		=> $is_control,
     		'is_push'			=> $is_push,
     		'applicationId'		=> $applicationId,
     		'stream_name'		=> $v,
     		'code'				=> $code,
     		'time_shift'		=> $time_shift,
     	);
     	
     	$function = 'set_stream_' . $type;
     	$set_stream = $this->$function($server_info, $_channel_stream);
     	
     	$ret_input_id[$k]  = $set_stream['ret_input_id'];
     	$ret_delay_id[$k]  = $set_stream['ret_delay_id'];
     	$ret_change_id[$k] = $set_stream['ret_change_id'];
     	$ret_output_id[$k] = $set_stream['ret_output_id'];
     	
     	$ret_live_output_id[$k]   = $set_stream['ret_live_output_id'];
     	$ret_record_output_id[$k] = $set_stream['ret_record_output_id'];
     	
     	$channel_stream[$k] = array(
     		'stream_name'	=> $v,
     		'url'			=> $url[$k],
     		'input_id'		=> $ret_input_id[$k],
     		'delay_id'		=> $ret_delay_id[$k],
     		'change_id'		=> $ret_change_id[$k],
     		'output_id'		=> $ret_output_id[$k],
     		'bitrate'		=> $bitrate[$k],
     		'is_main'		=> ($main_stream_name == $v) ? 1 : 0,
     		'order_id'		=> $k,
     	);
     	if($main_stream_name == $v)
     	{
     		$main_stream_url = $url[$k];
     	}
     }
     
     //如果创建过程中有失败,则删除以创建好的
     $tmp_delete = 0;
     for ($j = 0; $j < $core_count; $j ++)
     {
     	if (!$ret_output_id[$j])
     	{
     		$tmp_delete = 1;
     	}
     	
     	//直播
     	if ($live_host && !$ret_live_output_id[$j])
     	{
     		$tmp_delete = 1;
     	}
     	
     	//录制
     	if ($record_host && !$ret_record_output_id[$j])
     	{
     		$tmp_delete = 1;
     	}
     }
     
     if ($tmp_delete)
     {
     	for ($i = 0; $i < $core_count; $i ++)
     	{
     		$_channel_stream = $channel_stream[$i];
     		$_channel_stream['code'] 	   	= $code;
     		$_channel_stream['is_control'] 	= $is_control;
     		$_channel_stream['delay'] 		= $delay;
     		$_channel_stream['is_live'] 	= $is_live;
     		$_channel_stream['is_record'] 	= $is_record;
     		
     		$function = 'stream_operate_' . $type;
     		$this->$function($server_info, $_channel_stream, 'delete');
     	}
     	
     	//删除应用
     	if ($applicationId)
     	{
     		$application_data = array(
     			'action'	=> 'delete',
     			'id'		=> $applicationId,
     		);
     		$this->mLivemms->outputApplicationOperate($host, $output_dir, $application_data);
     		
     		//直播
     		if ($live_host)
     		{
     			$this->mLivemms->outputApplicationOperate($live_host, $output_dir, $application_data);
     		}
     		
     		//录制
     		if ($record_host)
     		{
     			$this->mLivemms->outputApplicationOperate($live_host, $output_dir, $application_data);
     		}
     	}
     	
     	$this->errorOutput('流媒体服务器创建失败');
     }
     */
     $data = array('name' => $name, 'code' => $code, 'main_stream_name' => $main_stream_name, 'stream_name' => serialize($stream_name), 'stream_count' => $stream_count, 'core_count' => $core_count, 'application_id' => $applicationId, 'time_shift' => $time_shift, 'is_audio' => $is_audio, 'is_push' => $is_push, 'is_control' => $is_control, 'server_id' => $server_id, 'org_id' => $this->user['org_id'], 'user_id' => $this->user['user_id'], 'user_name' => $this->user['user_name'], 'appid' => $this->user['appid'], 'appname' => $this->user['display_name'], 'create_time' => TIMENOW, 'update_time' => TIMENOW, 'ip' => hg_getip(), 'can_record' => 1, 'record_uri' => $this->input['record_uri']);
     //发布开始
     //$data['column_id'] = $this->mPublishColumn->get_columnname_by_ids('id,name', $column_id);
     //$data['column_id'] = $data['column_id'] ? serialize($data['column_id']) : '';
     //发布结束
     //创建播控和串联单两层输出
     $from_control_stream = '';
     if ($data['is_control'] && $this->settings['schedule_control_wowza']['is_wowza']) {
         if (count($channel_stream) > 1) {
             $this->errorOutput("多码流不支持播空和串联单");
         }
         $_schedule_control = array();
         $_schedule_control_data = array('url' => $main_stream_url, 'type' => $is_push, 'action' => 'insert');
         if ($this->settings['schedule_control_wowza']['is_wowza'] && !($_schedule_control = $this->create_schedule_control($_schedule_control_data))) {
             $this->errorOutput("创建播控层[或串联单层]失败");
         }
         if ($_schedule_control) {
             $data['schedule_control'] = serialize($_schedule_control);
         }
         $from_control_stream = "rtmp://" . str_replace(':8086', '', $this->settings['schedule_control_wowza']['host']) . "/input/" . $_schedule_control['control']['output_id'] . ".output";
     }
     /******************** 检查TS目录存储 *************************/
     include CUR_CONF_PATH . 'lib/' . $type . '.live.php';
     $server = new m2oLive();
     //查出所有使用该直播配置的信号流占用的存储
     $sql = "SELECT c_s.bitrate,c.time_shift FROM " . DB_PREFIX . "channel_stream c_s \r\n\t\t\t\tLEFT JOIN " . DB_PREFIX . "channel c ON c_s.channel_id = c.id \r\n\t\t\t\tWHERE c.server_id = " . $server_id;
     $q = $this->db->query($sql);
     $used_size = 0;
     while ($row = $this->db->fetch_array($q)) {
         $used_size += $row['bitrate'] * $row['time_shift'] * 3600;
     }
     //新添加的信号流所需的存储
     $bitrate = 0;
     if (is_array($channel_stream)) {
         foreach ($channel_stream as $k => $v) {
             $bitrate += $v['bitrate'];
         }
     }
     //所需存储总数 (码流单位kbps, 存储单位b)
     $needsize = (3600 * $time_shift * $bitrate + $used_size) * 1024;
     //取主、备配置
     $sql = "SELECT host,input_dir,hls_path,fid FROM " . DB_PREFIX . "server_config WHERE id = " . $server_id . " OR fid = " . $server_id;
     $query = $this->db->query($sql);
     while ($row = $this->db->fetch_array($query)) {
         $row_b[] = $row;
         $init_data = array('host' => $row['host'], 'dir' => $row['input_dir']);
         $server->init_env($init_data);
         if (!$server->check_ts_path(array('needsize' => $needsize, 'hls_path' => $row['hls_path']))) {
             $this->errorOutput('主机' . $init_data['host'] . '所设置的TS目录存储不足');
         }
     }
     /**************************************************************/
     //入本地库
     $ret = $this->mChannel->create($data);
     if (!$ret['id']) {
         $this->errorOutput('添加失败');
     }
     /*************** 设置dvr表(按照n个频道共用一组表的机制为该频道自动选择dvr表) *********
     		$sql = "SELECT COUNT(DISTINCT table_name) AS total FROM " .DB_PREFIX. "channel WHERE id != " .$ret['id'];
     		$r = $this->db->query_first($sql);
     		$table_count = $r['total']; //已有dvr表个数
     		if($table_count == 1)
     		{
     			$table_name_tmp = DB_PREFIX . 'dvr';
     		}
     		else
     		{
     			$table_name_tmp = DB_PREFIX . 'dvr' . $table_count;
     		}
     		$sql2 = "SELECT COUNT(*) AS total2 FROM " .DB_PREFIX. "channel WHERE table_name = '" .$table_name_tmp. "'";
     		$r2 = $this->db->query_first($sql2);
     		$channel_num = $r2['total2'];
     		if($channel_num < $this->settings['channel_table_limit'])
     		{
     			$table_name = $table_name_tmp;
     		}
     		else
     		{
     			//如果使用该表的频道数超过限制,就按照表名+1的规则新建一张表
     			$table_count += 1;
     			$table_name = DB_PREFIX . 'dvr' . $table_count;
     			$sql = "CREATE TABLE " .$table_name. " LIKE " .DB_PREFIX. "dvr";
     			$sql2 = "CREATE TABLE " .$table_name. "_1 LIKE " .DB_PREFIX. "dvr";
     			$this->db->query($sql);
     			$this->db->query($sql2); //创建直播时移备份表
     		}
     		//更新表名字段
     		$sql = "UPDATE " .DB_PREFIX. "channel SET table_name = '" .$table_name. "' WHERE id = " .$ret['id'];
     		$this->db->query($sql);
     		***************************************************************************/
     /*************** 设置dvr表(按照n个频道共用一组表的机制为该频道自动选择dvr表) *********/
     //查出目前每个表所占用的频道数
     $sql = "SELECT table_name, count(*) AS total FROM " . DB_PREFIX . "channel WHERE 1 group by table_name";
     $que = $this->db->query($sql);
     while ($row = $this->db->fetch_array($que)) {
         $channel_table[] = $row['table_name'];
         if ($row['total'] < $this->settings['channel_table_limit']) {
             $useable[] = $row['table_name'];
             //找出可用的dvr表
         }
     }
     //如果没有可用的dvr表,就给该频道挑选一张合适的dvr表
     if (!$useable) {
         $tablename = select_table($channel_table);
     } else {
         $tablename = $useable[0];
     }
     $tablename_1 = $tablename . '_1';
     //构建备份表
     //如果选定的表不存在,就创建
     $query = $this->db->query_first("SHOW TABLES LIKE '" . DB_PREFIX . $tablename . "'");
     if (!$query) {
         $sql = "CREATE TABLE " . DB_PREFIX . $tablename . " LIKE " . DB_PREFIX . "dvr";
         $sql2 = "CREATE TABLE " . DB_PREFIX . $tablename_1 . " LIKE " . DB_PREFIX . "dvr";
         $this->db->query($sql);
         $this->db->query($sql2);
         //创建备份表
     }
     //更新表名字段
     $sql = "UPDATE " . DB_PREFIX . "channel SET table_name = '" . $tablename . "' WHERE id = " . $ret['id'];
     $this->db->query($sql);
     /*****************************************************************************/
     //同步数据至串联单的channel_server
     $this->schedule_syn_channel_server($_schedule_control, $ret['id']);
     //同步结束
     $id = $ret['id'];
     $data['id'] = $id;
     //频道信号
     /*
     foreach ($channel_stream AS $k => $v)
     {
     	$v['channel_id'] = $id;
     	
     	if ($k == $is_default)
     	{
     		$v['is_default'] = 1;
     	}
     	$ret_channel_stream = $this->mChannel->channel_stream_create($v);
     	
     	if (!$ret_channel_stream)
     	{
     		continue;
     	}
     }
     */
     //长方形logo
     if ($_FILES['logo_rectangle']['tmp_name']) {
         $logo_rectangle = $this->mChannel->add_material($_FILES['logo_rectangle'], $id);
     }
     $data['logo_rectangle'] = $logo_rectangle ? serialize($logo_rectangle) : '';
     //方形logo
     if ($_FILES['logo_square']['tmp_name']) {
         $logo_square = $this->mChannel->add_material($_FILES['logo_square'], $id);
     }
     $data['logo_square'] = $logo_square ? serialize($logo_square) : '';
     /*
     //音频logo
     if ($_FILES['logo_audio']['tmp_name'])
     {
     	$logo_audio = $this->mChannel->add_material($_FILES['logo_audio'], $id);
     }
     
     $data['logo_audio'] = $logo_audio ? serialize($logo_audio) : '';
     */
     if (!empty($_FILES['client_logo'])) {
         $client_logo = array();
         foreach ($_FILES['client_logo'] as $k => $v) {
             ${$k} = $v;
             foreach (${$k} as $kk => $vv) {
                 $client_logo[$kk][$k] = $vv;
             }
         }
         $_client_logo = array();
         foreach ($client_logo as $appid => $logo) {
             $_client_logo[$appid] = $this->mChannel->add_material($logo, $id);
             $_client_logo[$appid]['appid'] = $_appid[$appid];
             $_client_logo[$appid]['appname'] = $_appname[$appid];
         }
     }
     $data['client_logo'] = $_client_logo ? serialize($_client_logo) : '';
     $data['order_id'] = $id;
     //更新 排序id、长方形logo、方形logo
     $update_data = array('id' => $id, 'order_id' => $data['order_id'], 'logo_rectangle' => $data['logo_rectangle'], 'logo_square' => $data['logo_square'], 'client_logo' => $data['client_logo'], 'logo_audio' => $data['logo_audio']);
     //更新数据
     $ret = $this->mChannel->update($update_data);
     $this->mChannel->cache_channel($data['code']);
     /*
     if ($id)
     {
     	//放入发布队列
     	if(!empty($column_id))
     	{
     		$op = 'insert';
     		$this->publish_insert_query($id, $op, $data['user_name']);
     	}
     	
     	//日志
     	$this->addLogs('新增直播频道' , '' , $data , $data['name'], $data['id']) ;
     }
     */
     //向直播服务器发送数据库信息数据以及设置流、设置时移目录
     foreach ($row_b as $key => $val) {
         $init_data = array('host' => $val['host'], 'dir' => $val['input_dir']);
         $server->init_env($init_data);
         //发送数据库信息
         global $gDBconfig;
         $db_data = array('mysql_host' => $gDBconfig['host'], 'mysql_user' => $gDBconfig['user'], 'mysql_password' => $gDBconfig['pass'], 'mysql_name' => $gDBconfig['database'], 'mysql_table' => 'liv_dvr', 'post_streamname_url' => $this->settings['App_live']['protocol'] . $this->settings['App_live']['host'] . '/' . $this->settings['App_live']['dir'] . 'build_m3u8.php?m2o_ckey=' . CUSTOM_APPKEY);
         if (!$server->set_database($db_data)) {
             $this->errorOutput('数据库信息发送失败');
         }
         //多码流频道创建
         if ($channel_stream) {
             foreach ($channel_stream as $k => $v) {
                 $v['channel_id'] = $id;
                 if ($k == $is_default) {
                     $v['is_default'] = 1;
                 }
                 if (!$val['fid']) {
                     $this->mChannel->channel_stream_create($v);
                 }
                 $create_data = array('url' => $from_control_stream ? $from_control_stream : $v['url'], 'name' => build_nginx_stream_name($code, $v['stream_name']), 'playlen' => $time_shift, 'mysql_table' => $val['fid'] ? DB_PREFIX . $tablename_1 : DB_PREFIX . $tablename);
                 if (!$is_push) {
                     //对接nginx创建流
                     if (!$server->create($create_data)) {
                         $this->errorOutput("服务器新增流失败,请稍后更新重试");
                     }
                 }
                 //设置时移
                 if (!$server->set_timeshift_length($create_data)) {
                     $this->errorOutput("设置时移失败");
                 }
                 //设置时移目录
                 $path_data = array('app' => 'live', 'name' => $create_data['name'], 'hls_path' => $val['hls_path']);
                 if (!$server->set_timeshift_path($path_data)) {
                     $this->errorOutput('设置时移目录失败');
                 }
             }
         }
     }
     $this->addItem($data);
     $this->output();
 }