精华内容
下载资源
问答
  • TS:链表

    2020-12-27 14:04:17
    == null){ str += cur.value + ' ' cur = cur.next } str = str.trim() return str } } 多重链表 链表中的节点包含多个指针,指向不同链表,构成多重链表,如十字链 节点包含多个指针不一定是多重...

    链表

    有序元素集合,逻辑上存在连续关系,物理上不需要连续存储

    单向链表

    type ListNode<T> = {
    	value: T
    	next: ListNode<T> | null
    }
    
    class LinkedListNode<T> implements ListNode<T> {
    	value: T
    	next: ListNode<T> | null
    	constructor(value:T){
    		this.value = value;
    		this.next = null;
    	}
    }
    
    class LinkedList<T> {
    	private head: ListNode<T> | null = null
    	private length: number = 0
    	constructor(headValue:T){
    		if(headValue !== undefined){
    			this.head = new LinkedListNode(headValue);
    			this.length ++;
    		}
    	}
    	getHead(){
    		return this.head;
    	}
    	size(){
    		return this.length;
    	}
    	append(nextValue:T):void {
    		if(this.head === null){
    			this.head = new LinkedListNode(nextValue);
    		}else{
    			let cur = this.head;
    			while(cur.next !== null){
    				cur = cur.next
    			}
    			cur.next = new LinkedListNode(nextValue);
    		}
    		this.length ++
    	}
    	remove(value:T){
    		if(this.head !== null){
    			if(this.head.value === value){
    				// let tmp = this.head
    				// this.head = tmp.next;
    				// tmp = null
    				// 注:手动释放
    				this.head = this.head.next;
    				// 注:JS自动内存回收机制会将原head指向的对象释放,可以不手动释放
    				this.length --
    			}else{
    				let cur = this.head
    				while(cur.next !== null && cur.next.value !== value){
    					cur = cur.next
    				}
    				if(cur.next.value === value){
    					cur.next = cur.next.next;
    					this.length --
    				}
    			}
    		}
    	}
    	insert(position:number, value:T){
    		if(position >= 0 && position <= this.length){
    			if(position === 0){
    				let tmp = new LinkedListNode(value);
    				tmp.next = this.head 
    				this.head = tmp;
    			}else{
    				let cur = this.head
    				let ind = 1;
    				while(ind !== position){
    					cur = cur.next;
    					ind ++;
    				}
    				let tmp = new LinkedListNode(value);
    				tmp.next = cur.next;
    				cur.next = tmp;
    			}
    			this.length ++
    		}
    	}
    	removeAt(position:number){
    		if(position >= 0 && position < this.length){
    			if(position === 0){
    				this.head = this.head.next;
    			}else{
    				let cur = this.head
    				let ind = 1;
    				while(ind !== position){
    					cur = cur.next
    					ind ++;
    				}
    				let tmp = cur.next;
    				cur.next = tmp.next;
    				tmp = null					
    			}
    			this.length --
    		}
    	}
    	indexOf(value:T):number{
    		if(this.head !== null){
    			let cur = this.head
    			let ind = 0;
    			while(cur !== null && cur.value !== value){
    				cur = cur.next
    				ind ++
    			}
    			if(cur.value === value){
    				return ind
    			}
    		}
    		return -1
    	}
    	isEmpty():boolean {
    		return this.length === 0
    	}
    	toString():string{
    		let cur = this.head
    		let str = ' ';
    		while(cur !== null){
    			str += cur.value + ' '
    			cur = cur.next
    		}
    		str = str.trim() 
    		return str 
    	}
    }
    

    双向链表

    type ListNode<T> = {
    	value: T
    	prev: ListNode<T> | null
    	next: ListNode<T> | null
    }
    
    class LinkedListNode<T> implements ListNode<T> {
    	value: T
    	prev: ListNode<T> | null
    	next: ListNode<T> | null
    	constructor(value:T){
    		this.value = value;
    		this.prev = null;
    		this.next = null;
    	}
    }
    
    class LinkedList<T> {
    	private head: ListNode<T> | null = null
    	private tail: ListNode<T> | null = null
    	private length: number = 0
    	constructor(headValue:T){
    		if(headValue !== undefined){
    			this.head = new LinkedListNode(headValue);
    			this.length ++;
    		}
    	}
    	getHead(){
    		return this.head;
    	}
    	getTail(){
    		return this.tail;
    	}
    	size(){
    		return this.length;
    	}
    	append(nextValue:T):void {
    		if(this.head === null){
    			this.head = new LinkedListNode(nextValue);
    		}else{
    			let cur = this.head;
    			while(cur.next !== null){
    				cur = cur.next
    			}
    			let node = new LinkedListNode(nextValue);
    			node.prev = cur
    			cur.next = node
    		}
    		this.length ++
    	}
    	remove(value:T){
    		if(this.head !== null){
    			if(this.head.value === value){
    				this.head = this.head.next;
    				this.head.prev = null
    				this.length --
    			}else{
    				let cur = this.head
    				while(cur.next !== null && cur.next.value !== value){
    					cur = cur.next
    				}
    				if(cur.next.value === value){
    					cur.next = cur.next.next;
    					cur.next.prev = cur
    					this.length --
    				}
    			}
    		}
    	}
    	insert(position:number, value:T){
    		if(position >= 0 && position <= this.length){
    			if(position === 0){
    				let node = new LinkedListNode(value);
    				node.next = this.head 
    				node.next.prev = node;
    				this.head = node;
    			}else{
    				let cur = this.head
    				let ind = 1;
    				while(ind !== position){
    					cur = cur.next;
    					ind ++;
    				}
    				let node = new LinkedListNode(value);
    				node.next = cur.next;
    				node.next.prev = node;
    				node.prev = cur
    				node.prev.next = node;
    			}
    			this.length ++
    		}
    	}
    	removeAt(position:number){
    		if(position >= 0 && position < this.length){
    			if(position === 0){
    				this.head = this.head.next;
    				this.head.prev = null
    			}else{
    				let cur = this.head
    				let ind = 1;
    				while(ind !== position){
    					cur = cur.next
    					ind ++;
    				}
    				cur.next = cur.next.next;
    				cur.next.prev = cur
    			}
    			this.length --
    		}
    	}
    	indexOf(value:T):number{
    		if(this.head !== null){
    			let cur = this.head
    			let ind = 0;
    			while(cur !== null && cur.value !== value){
    				cur = cur.next
    				ind ++
    			}
    			if(cur.value === value){
    				return ind
    			}
    		}
    		return -1
    	}
    	isEmpty():boolean {
    		return this.length === 0
    	}
    	toString():string{
    		let cur = this.head
    		let str = ' ';
    		while(cur !== null){
    			str += cur.value + ' '
    			cur = cur.next
    		}
    		str = str.trim() 
    		return str 
    	}
    }
    

    多重链表

    链表中的节点包含多个指针,指向不同链表节点,构成多重链表,如十字链表
    节点包含多个指针不一定是多重链表,如双向链表
    下面用十字链表实现稀疏矩阵

    // todo
    
    展开全文
  • TS实现链表结构

    2020-09-25 08:32:00
    戳蓝字"前端优选"关注我们哦!前面的几篇文章做了很多铺垫,学习TypeScript的一些基本入门知识,这次将使用TS来实现链表结构,并实现链表的反转操作。什么是链表链表是...

    戳蓝字"

    前端优选

    "

    关注我们哦

    前面的几篇文章做了很多铺垫,学习TypeScript的一些基本入门知识,这次将使用TS来实现链表结构,并实现链表的反转操作。

    什么是链表

    链表是用来存储有序的元素集合,与数组不同,链表中的元素并非保存在连续的存储空间内,而是由每个元素本身的节点和一个指向下一个元素的指针构成。当要移动或删除元素时,仅需对元素上的指针进行修改即可,对比数组元素的操作效率,链表则更胜一筹。

    因此,需要首选定义一个元素节点的接口,然后去实现它:

    //由于Node属于内置类,这里给节点起的名字规避了Node
    interface Nodea{
        element: number;
        next: object;
    }
    class Nodea implements Nodea{
        public element:number;
        public next:object;
        constructor(element:number,next:object){
            this.element = element;
            this.next = next;
        }
    }
    

    定义接口的element和next属性,然后再通过类进行具体实现。这里规定存放的值即为数字。

    接下来就是要生成一个链表。

    创建链表

    首先创建一个类,它具有head属性和size属性,head是链表的头,用来记录链表的第一个元素节点;size用来描述当前链表的长度,在后续的遍历中将会用到。

    class LinkList{
        public head;
        public size;
        constructor(){
            this.head = null;
            this.size = 0;
        }
    }
    

    链表还有很多操作方法,例如:add,remove,getNode,indexOf,length,empty等等,这里我们将只实现主要方法,其他方法大家可以根据兴趣自行尝试一下。

    getNode

    获取其中一个元素,该方法较其他方法更为基础,因此第一个 先实现它。

    getNode(index:number):Nodea{
        let current = this.head;
        for(let i=0;i<index;i++){
            current = current.next;
        }
        return current;
    }
    

    通过要查找的索引,逐层遍历并返回相应元素。这里规定了参数必须为Number类型,返回的是Nodea实例。

    add

    添加元素节点

    add(index:number,element?:number):void{
        if(arguments.length == 1){
            element = index;
            index = this.size;
        }
        if(index < 0 || index > this.size) throw new Error('创建索引异常!');
        if(index == 0){
         let head = this.head;
         this.head = new Nodea(element,head);
        }else{
         let prevNode:Nodea = this.getNode(index - 1);
         prevNode.next = new Nodea(element,prevNode.next);
        }
        this.size ++;
    }
    

    创建元素,可以根据索引在指定位置插入,也可默认将新建元素插入到链表的末尾,因此该方法的element为可选参数。当只有一个参数时,直接将该元素放到链表最后。

    let ll = new LinkList();
    ll.add(0,88);
    ll.add(99);
    //Nodea { element: 88, next: Node { element: 99, next: null } }
    

    当创建索引为0时,则该元素直接为链表的新头部元素;当索引不为0时,则将记录该索引处的前后元素指针,用新元素来记录前后节点,达到插入元素的目的。

    let ll = new LinkedList();
    ll.add(0,88);
    ll.add(0,77);
    ll.add(99);
    //Node { element: 99, next: Node { element: 88, next: Node { element: 77, next: null } }}
    

    插入元素成功后,别忘了size++,这一点很重要。

    remove

    删除链表元素,主要在于定位元素:

    remove(index:number):Nodea{
        let oldNode;
        if(index == 0){
         oldNode = this.head;
            this.head = oldNode && oldNode.next;
        }else{
         let prevNode:Nodea = this.getNode(index-1);
          oldNode = prevNode.next;
         prevNode.next = oldNode.next;
        }
        this.size --;
        return oldNode && oldNode.element;
    }
    

    如果索引为0,则将头部直接指向下一个元素即可;如果索引不为0,则需要通过getNode方法查找到对应位置,然后改变元素的next指针,达到删除的目的。

    同时,可以将删除的元素返回,并将size--

    length

    这是最简单的一个方法,获取链表的长度:

    length():number{
     return this.size;
    }
    

    这里直接使用链表的size属性,因此在改变链表长度的时候,一定要记得增加或减小size属性。

    链表反转

    链表有很多种操作方法,这里介绍一个最常见的,就是链表反转。

    reverseLinkList():LinkList{
        let head = this.head;
        if(head == null || head.next == null) return head;
        let newHead = null;
        while(head !== null){
            let temp = head.next;
            head.next = newHead;
            newHead = head;
            head = temp;
        }
        this.head = newHead
        return this.head;
    }
    

    这里使用一个临时变量来存放元素,然后做到相互交换的效果,达到反转的目的。类似下面这张图:

    通过临时变量达到互换的目的。

    let ll = new LinkedList();
    ll.add(0,88);
    ll.add(0,77);
    ll.add(99);
    let reverse = ll.reverseLinkList();
    //Nodea {element: 99,next: Nodea { element: 88, next: Nodea { element: 77, next: null } }}
    

    到此,一个简单的链表实现和操作就完成了,对于TS的应用可能还有不详尽的地方,欢迎大家指出交流~

    历史好文推荐:

    1、TypeScript入门指北(一)                       

    2、TypeScript入门指北(二                        

    3、TypeScript入门指北(三                           

    ❤️ 感谢大家

    如果你觉得这篇内容对你挺有有帮助的话:

    1. 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)

    2. 关注公众号【前端优选】,定期为你推送好文。

    添加个人微信,进群与小伙伴一起玩耍(已经推出)~

    点个在看,大家都看 

    展开全文
  • 前面的几篇文章做了很多铺垫,学习TypeScript的一些基本入门知识,这次将使用TS来实现链表结构,并实现链表的反转操作。什么是链表链表是用来存储有序的元素集合,与数组不同,链表中的元素并非保存在连续的存储空间...

    0ceee7e6b3171475b6747b974040d41f.gif戳蓝字"前端优选"关注我们哦

    前面的几篇文章做了很多铺垫,学习TypeScript的一些基本入门知识,这次将使用TS来实现链表结构,并实现链表的反转操作。

    什么是链表

    链表是用来存储有序的元素集合,与数组不同,链表中的元素并非保存在连续的存储空间内,而是由每个元素本身的节点和一个指向下一个元素的指针构成。当要移动或删除元素时,仅需对元素上的指针进行修改即可,对比数组元素的操作效率,链表则更胜一筹。

    因此,需要首选定义一个元素节点的接口,然后去实现它:

    //由于Node属于内置类,这里给节点起的名字规避了Node
    interface Nodea{
        element: number;
        next: object;
    }
    class Nodea implements Nodea{
        public element:number;
        public next:object;
        constructor(element:number,next:object){
            this.element = element;
            this.next = next;
        }
    }

    定义接口的element和next属性,然后再通过类进行具体实现。这里规定存放的值即为数字。

    接下来就是要生成一个链表。

    创建链表

    首先创建一个类,它具有head属性和size属性,head是链表的头,用来记录链表的第一个元素节点;size用来描述当前链表的长度,在后续的遍历中将会用到。

    class LinkList{
        public head;
        public size;
        constructor(){
            this.head = null;
            this.size = 0;
        }
    }

    链表还有很多操作方法,例如:add,remove,getNode,indexOf,length,empty等等,这里我们将只实现主要方法,其他方法大家可以根据兴趣自行尝试一下。

    getNode

    获取其中一个元素,该方法较其他方法更为基础,因此第一个 先实现它。

    getNode(index:number):Nodea{
        let current = this.head;
        for(let i=0;i        current = current.next;
        }
        return current;
    }

    通过要查找的索引,逐层遍历并返回相应元素。这里规定了参数必须为Number类型,返回的是Nodea实例。

    add

    添加元素节点

    add(index:number,element?:number):void{
        if(arguments.length == 1){
            element = index;
            index = this.size;
        }
        if(index 0 || index > this.size) throw new Error('创建索引异常!');
        if(index == 0){
         let head = this.head;
         this.head = new Nodea(element,head);
        }else{
         let prevNode:Nodea = this.getNode(index - 1);
         prevNode.next = new Nodea(element,prevNode.next);
        }
        this.size ++;
    }

    创建元素,可以根据索引在指定位置插入,也可默认将新建元素插入到链表的末尾,因此该方法的element为可选参数。当只有一个参数时,直接将该元素放到链表最后。

    let ll = new LinkList();
    ll.add(0,88);
    ll.add(99);
    //Nodea { element: 88, next: Node { element: 99, next: null } }

    当创建索引为0时,则该元素直接为链表的新头部元素;当索引不为0时,则将记录该索引处的前后元素指针,用新元素来记录前后节点,达到插入元素的目的。

    let ll = new LinkedList();
    ll.add(0,88);
    ll.add(0,77);
    ll.add(99);
    //Node { element: 99, next: Node { element: 88, next: Node { element: 77, next: null } }}

    插入元素成功后,别忘了size++,这一点很重要。

    remove

    删除链表元素,主要在于定位元素:

    remove(index:number):Nodea{
        let oldNode;
        if(index == 0){
         oldNode = this.head;
            this.head = oldNode && oldNode.next;
        }else{
         let prevNode:Nodea = this.getNode(index-1);
          oldNode = prevNode.next;
         prevNode.next = oldNode.next;
        }
        this.size --;
        return oldNode && oldNode.element;
    }

    如果索引为0,则将头部直接指向下一个元素即可;如果索引不为0,则需要通过getNode方法查找到对应位置,然后改变元素的next指针,达到删除的目的。

    同时,可以将删除的元素返回,并将size--

    length

    这是最简单的一个方法,获取链表的长度:

    length():number{
     return this.size;
    }

    这里直接使用链表的size属性,因此在改变链表长度的时候,一定要记得增加或减小size属性。

    链表反转

    链表有很多种操作方法,这里介绍一个最常见的,就是链表反转。

    reverseLinkList():LinkList{
        let head = this.head;
        if(head == null || head.next == nullreturn head;
        let newHead = null;
        while(head !== null){
            let temp = head.next;
            head.next = newHead;
            newHead = head;
            head = temp;
        }
        this.head = newHead
        return this.head;
    }

    这里使用一个临时变量来存放元素,然后做到相互交换的效果,达到反转的目的。类似下面这张图:

    70d945762e1642366096c97e215ebd1e.gif

    通过临时变量达到互换的目的。

    let ll = new LinkedList();
    ll.add(0,88);
    ll.add(0,77);
    ll.add(99);
    let reverse = ll.reverseLinkList();
    //Nodea {element: 99,next: Nodea { element: 88, next: Nodea { element: 77, next: null } }}

    到此,一个简单的链表实现和操作就完成了,对于TS的应用可能还有不详尽的地方,欢迎大家指出交流~

    60132433a012d64ae996d82b2e5dc6a1.png

    历史好文推荐:

    1、TypeScript入门指北(一)                       

    2、TypeScript入门指北(二)                        

    3、TypeScript入门指北(三)                           

    58b70772cbf9e7e1f61c3d1abd161723.gif

    ❤️ 感谢大家

    如果你觉得这篇内容对你挺有有帮助的话:

    1. 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)

    2. 关注公众号【前端优选】,定期为你推送好文。

    4bdbc19a407b5df9d3c1d2cdad709038.png

    添加个人微信,进群与小伙伴一起玩耍(已经推出)~

    c93d158b960f2503eda6a93712d25a6d.png

    点个在看,大家都看 e444586c77b5cab3178a94daf6edfb13.gif

    展开全文
  • 模板表达微服务 :desktop_computer: :lollipop: Typescript中的裸分快递微服务模板 :face_with_monocle:里面有什么 快递终点 添加了插件以验证输入 开玩笑地测试: 用超级测试进行端点测试 正常单元测试 ...
  • TS携带 PSI SI等的数据时,各个以各对应的Section语法格式做为传输单元存放到TS包中 以便传输;  TS包,有一个TS包的PID,系统就是根据这个PID来找对应的TS包;对于包含音视频数据(PES包)的TS包,系统通过...
      TS流,通过一个个的TS包来传送; TS包可以是传送PSI SI等各表的数据包,也可以是传送节目音视频数据(携带的PES包:音视频基本流包)的包;TS携带 PSI SI等表的数据时,各个表以各表对应的Section语法格式做为传输单元存放到TS包中 以便传输;
      TS包,有一个TS包的PID,系统就是根据这个PID来找对应的TS包;对于包含音视频数据(PES包)的TS包,系统通过TS的PID找到对应TS数据包,提取其中的数据组合成节目的音视频;对于携带PSI SI等数据的TS包,系统通过TS的PID找到对应TS数据包,提取各个PSI SI数据表格,用来指导系统。
      有了TS的PID后, 如果TS包携带的是PSI SI等表格的Section数据时,有时还不能确定该PID的TS包中携带的数据是什么,SDT BAT ST 等表传送时,都用的是PID为0X0011的TS数据包,对于这种携带PSI SI Section单元的TS包,对应的数据(表的Section语法中)还有一个 TABLE_ID字段,用来可以确定是具体的什么表。
      每不同的表中,我们看表的SECTION语法,都会看到descriptor()字样,descriptor()表示的也是一个语法结构,他具体对应的语法结构,由他内部的descriptor tag字段决定,各个表的具体的定义,可以参见13818对应的定义,其中这里面还可以有用户的自定义描述。
      
      •PSI(Program Specific Information)
      –PAT (Program Association Table)节目关联表
      –PMT(Program Map Table)节目映射表
      –CAT(Conditional Access Table)条件接收表
      •SI(Service Information) 
      –NIT(Network Information Table)网络信息表
      –SDT(ServiceDiscription Table)业务描述信息表
      –BAT(Bouquet Association Table)业务群信息表
      –EIT(Event Information Table)节目事件信息表
      –TDT(Time and Data Table)
      日期时间表
      •事件 event
        –一组给定了起始时间和结束时间、属于同一业务的基本广播数据流。例如:一场足球比赛的半场、新闻快报或娱乐表演的第一部分
      •节目  programme
        –由广播者提供的一个或多个连续的事件。例如:新闻广播,娱乐广播。
      •网络  network
        一个传输系统,可以传输一组MPEG-2传输流(TS)。例如:某个有线电视系统中的所有数字频道
      •业务  service
        –在广播者的控制下,可以按照时间表分步广播的一系列节目,我们也称之个频道,口语中也称之为节目
      节目关联表PAT
        •PAT定义了一个TS流中所有的节目,PAT的PID是0x0000,他是PSI信息的根节点。要查找节目播放信息必须从PAT开始。
        •PAT中包含了TS中所有节目的完整列表,每个表项包括ServiceID  和PMT(用于播放)的PID。
        •PAT中ServiceID 为0的表项表示NIT。
      节目映射表PMT
        •  PMT提供了一个节目的ServiceID和用于播放的所有资源信息,例如音视频PID,PCR,字幕PID等。
        •  简单的说,PMT完整的描述了一路节目是由哪些PES组成,给播放提供相应的资源。
        •  PAT与PMT关系
      条件访问表CAT
        •CAT提供了在一个或多个CA系统及其授权管理信息,用于节目的解扰工作。
        •如果在一个TS中任何原始流进行了加密处理,那么在TS中一定要插入CAT。
        •在CAT中,最重要的字段就是CA_descriptor()段。下面将简单讲述一下该描述段
        •CA_descriptor用来表示含有ECM或者是EMM信息的TS的PID,即CA_PID。
          –当CA_descriptor出现在PMT中时,CA_PID指向含有与访问控制信息(ECM)相关的节目包。
          –当CA_descriptor出现在CAT中时,CA_PID指向含有与授权管理信息(EMM)相关的节目包。
        •CA_descriptor中几个重要的字段如下:
          –CA_system_ID:该字段表示适用于相关ECM和/或EMM流的CA系统类型。其值是用户定义的。
          –CA_PID:该字段表示传送流包的PID,此包中含有由相应的CA_system_ID指明的CA系统的ECM或EMM信息,由CA_PID指明的包的内容(ECM或EMM)所在的上下文决定,既由TS中的PMT、CAT或节目流中的stream_id字段决定。
     网络信息表NIT
      •NIT描述了一个DVB传输通道的所有物理参数,包括下列信息:
        –传输路径(卫星、电缆、地面)
        –接收频率
        –调制类型
        –误码保护
        –传输参数
      •机顶盒在扫描或变换信道时,可以存储一个物理信道的所有参数,便于以后很快跳回该信道。
      •信道中也可以传送相邻或其他信道的传输参数,使得信道转换灵活快捷。
      •如果NIT中的传输参数与实际不符,会对许多接收设备,如机顶盒,产生不可预知的影响。
        –如果NIT中的传输频率与实际接收频率不同,许多接收设备在没有任何原因提示的情况下,不产生任何图像和声音。
      SDT
        •SDT包含对TS流中节目(服务)的更多详细描述:
          –节目名称,如CNN,CBS,Eurosport,ARD,ZDF,BBC,ACB,SBS等等
          –在提供节目PID的同时,SDT对用户提供了文本信息。
          –通过提供文本列表,使得接收设备操作灵活。
        •BAT,与SDT密切相关:
          –BAT与SDT的PID相同,只是table ID不同。
          –SDT描述一个物理信道的节目结构。
          –BAT描述几个或大量物理信道的节目结构。
      BAT
        •BAT表是由DVB定义的,是一个SI表,因此它是一个全局表,一个数字电视系统只对应一个BAT表,其table_id=0X4A。
        •一个节目类别对应一个段。为了让受众能更方便地在众多的节目中寻找出自己喜欢的节目,往往需要提供一种把众多的节目频道进行分类的方法(一个类相当一个节目组)。
        •例如把电影频道归为“家庭影院”的类别,把电视连续剧归为“电视剧场”的类别等等,BAT表就提供了这一功能,每一个类别都用一个bouquet_id
     来标识。它包括了节目业务名称(类别)及节目组所包含的节目清单(节目列表)。BAT表在SI信息中属于可选表 
      EIT
        •EIT(event information table)
          –即DVB中的EPG(electronic program guide)表
          –包含一天或一周内所有广播的计划开始和结束时间。
          –结构非常灵活,允许传送大量附加信息
          –不是所有机顶盒都支持这一特性
          – 事件信息表EIT按时间顺序提供每一个业务所包含的事件的信息。按照不同table_id有四类EIT:
            –1)现行传输流,当前/后续事件信息= table_id = "0x4E";
            –2)其它传输流,当前/后续事件信息= table_id = "0x4F";
            –3)现行传输流,事件时间表信息= table_id = "0x50" 至 "0x5F";
            –4)其它传输流,事件时间表信息= table_id = "0x60" 至 "0x6F"。
          –现行传输流的所有EIT子表都有相同的transport_stream_id和original_network_id。
      TDT/TOT
        •机顶盒操作还需要传输当前时钟和当前日期,分两步:
          –TDT(time&date table)
        •传送GMT或UTC
        •即零度子午线的当前时刻
          –TOT(time offset table)
        •传送不同时区各自适当的时间偏移量
          –TDT和TOT中的信息如何计算以及计算到什么程度,取决于机顶盒的软件
          –对广播时间信息的完全支持还需要机顶盒得到当前的位置信息:
        •对拥有多个时区的国家,如澳大利亚和美国,这个问题尤其重要。
      其它表
        •运行状态表(RST):
          –运行状态表给出了事件的状态(运行/非运行)。运行状态表更新这些信息,允许自动适时切换事件。
        •填充表(ST):
          –填充表用于使现有的段无效,例如在一个传输系统的边界。
        •选择信息表(SIT):
          –选择信息表仅用于码流片段(例如,记录的一段码流)中,它包含了描述该码流片段的业务信息的概要数据。
        •间断信息表(DIT):
          –间断信息表仅用于码流片段(例如,记录的一段码流)中,它将插入到码流片段业务信息间断的地方。
        
        
        
     
      TS流的形成:前段音视频数据经过音视频编码器后音视频数据流ES,ES经过分组器(打包器)形成一个个的分组,即PES(音视频数据流ES的分组包,Packet ES,PES最长一般为188个字节);音视频PES再经过复合器,从而形成传输流TS,传输流以传输流分组(TS Packet);TS Packet中的有效数据既可以是PES(音视频ES分组包),也可以是PSI等信息数据,这个由TS Packet中的PID来指定负荷数据的类型;SI各表格是以SECTION为单位放到TS Packet中,因此不同的表格就要按标准遵循对应SECTION的语法;比如PMT表,PMT可能包含多个节目的描述,因此它可能会被划分为多个SECTION放到TS Packet中,遵循的语法就是TS_program_map_section() ;
        
     
        
         

        

        

        

     【通过码流分析工具的查看,800来个 PID为0X191的401节目的PMT SECTION TS包都是一样的】
      根据TS Packet 的语法,可以简要分析下上面的数据包:
      同步字节段:0X47(8bit)
      传输错误指示字符段:0(1bit)
      有效负载数据单元起始指示符字段:1(1bit)
      传输优先级字段:0(1bit)
      PID:0x191(13bit)(PAT表中指定该PID的TS包为包含PMT SECTION数据的TS包)
      传输加扰控制字段:(0x0)(2bit)
      调整字段控制字段:0x01(无调整字段,只有有效负载)(2bit)
      连续性计数器字段:(4bit)
      数据字节字段:这些数据 有可能是PES包,有可能是PSI SECTION (由PID决定),如果没有调整字段,从这开始就是负载数据了;
         若是PES数据,则这些负载数据通过PES分组语法来解析;
         若是PSI SECTION数据,则通过SECTION语法来解释,可通过第一个table_id来确定是哪一个表的SECTION;
     
        
        
        
     
      
    CAS原理:
        条件接收(CA)系统(CAS)是数字电视广播(DVB)实行收费所必须采用的系统,也是数字电视平台不可缺少的部分,CAS负责完成用户授权控制与管理信息的获取、生成、加密、发送以及节目调度控制等工作,保证只有已被授权的用户才能收看节目,从而保护节目制作商和广播运营商的利益。
        在DVB前端,CAS将通过加扰器节目级复用器复用后的节目内容,即MPEG-2/DVB视频、音频和辅助数据传输流(TS), 与一个加扰伪随机序列做XOR运算,这个伪随机加扰序列就是控制字发生器提供的控制字CW
        CW被业务密钥(SK加密处理后授权控制信息(ECM)数据流中传送SK被用户个人分配密钥(PDK加密处理后,在授权管理信息EMM数据流中传送,PDK存放在用户智能卡(Smard Card)中
        已加扰的MPEG-2/DVB视频、音频和辅助数据传输流(TS)、ECM、EMM数据流、节目说明信息(PSI)和业务信息(SI)等数据流,经复用后,从发送端经传输信道传送给接收端机顶盒(STB)。
        对于已经缴费的用户,其智能卡会被授权,STB从接收到的已加扰传输流中,解复用出ECM和EMM数据流后送给智能卡,智能卡首先读取PDK,用PDK对EMM解密得到SK,再用SK对ECM解密得到CW,利用CW由解扰器对已加扰传输流(TS)进行解扰后,再进行节目级解复用
        
        

    转载于:https://www.cnblogs.com/ThatsMyTiger/p/6866863.html

    展开全文
  • TS中pat

    2013-05-09 13:49:33
    Transport_stream_id: 16bit字段,当前TS流的ID,与网络中其他TS流相区别,由运营商指定。 Reserved: 2bit保留字段,用于将来扩展,置为11。 Version_number: 5bit字段,指出PAT的版本号,一旦PAT有...
  • 我们这里说的 section 就是段的概念,一个 section 可能包含一个或者多个TS包,我们可以这样理解,TS是对数据内容发封装,属于传输层的格式,规定了传输数据的格式,它以 188 字节为单位组成一个TS包,...
  • linked-list-ts:打字稿链表实现
  • 关键字 解释 翻译 备注 PSI Program Specific Information 节目引导信息 对单一码流的描述 SI Service Information ...对系统中所有码流的描述,包含了PSI(PSI+9张表) TS包 ...数字视音频、图文数据打包...节目关联 将节
  • TS科普18 节目映射PMT

    万次阅读 2015-12-04 09:33:00
    节目映射提供节目编号与组成它们的节目元之间的映射。此类映射的一个特例称之为“节目定义”。节目映射是传输流的所有节目定义的全面集成。此必须以包的形式传输,包的PID 值由编码器选择。若希望,可以使用多...
  • TS科普16 节目相关PAT

    万次阅读 2015-11-26 12:34:48
    节目相关提供program_number 和承载该节目定义的传输流包的PID 值之间的对应。program_number是同节目有关的数值标签。 PMT PAT
  • TS科普17 有条件访问

    万次阅读 2015-12-03 21:16:33
    有条件访问(CA)提供一个或多个CA 系统及其EMM 流之间的关系以及任何与它们有关的特殊参数。 该在一个或多个具有以下句法的分段中包含。它可以被分割占用多个分段。
  • 形如下边的配置 language["instrument_txt_open"] = "#level#级\n解锁神兵" language["camp_race_look_single_race_tip"] = "阵营竞技下周一开启,请主公积极报名参加" language["FUNC_CAMP_RACE"] = { { title =...
  • ts文件中插入SI

    2020-04-28 10:17:39
    一个办法是修改mpegtsenc.c, 我看见一个本科的毕业论文是这么搞的,但是不够灵活,得重新编译。 另一个办法是[ref1]: How to Use OpenCaster with FFmpeg background ...ffmpeg -i cctv5.ts -i ...
  • PID值 PAT 0x0000 CAT 0x0001 TSDT 0x0002 预留 0x0003至0x000F NIT, ST 0x0010 SDT , BAT, ST 0x0011 EIT...
  • TS-ME型多功能电量监测仪表是在消化国外进口同类产品的技术基础上,根据我国对电力设备的运行和计算机智能化监控要求而设计的,该产品集电流、电压、功率、功率因数、电度为一体的综合电量监测仪表,RS485...
  • 任务五 解析SDT,解出相关的节目信息,主要是service_id和节目名字以及供应商的名字等 相关知识 SDT是服务描述的简称,描述了业务...TABLE_ID = 0x42 (discribe actual TS,现行TS) TABLE_ID = 0x46 (discribe...
  • USER_TS_QUOTAS视图、DBA_TS_QUOTAS视图、空间权限关系第一步、创建空间jason,创建jason用户默认空间位jason。create tablespace jason datafile'/home/oracle/orabase/oradata/ORACLE/jason01.dbf' size 100...
  • Real-Time PCR检测非小细胞肺癌患者循环肿瘤细胞TUBB3、TS mRNA表达及意义,满迎春,金时,目的 应用Real-Time PCR(实时定量PCR)的方法检测非小细胞肺癌患者外周血循环肿瘤细胞中TUBB3、TS的mRNA表达,分析其对化疗...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,890
精华内容 1,156
关键字:

ts表