Day28_Stream流

本文介绍Java 8 Stream流如何简化集合遍历,演示如何使用filter、forEach、map等方法对集合进行高效操作,包括传统方式与Stream流对比,并提供小练习实例。

一、Stream流 和 传统的集合遍历

I/O Stream是用来读写的,Stream流是用来优化原有集合的弊端来遍历集合的

1.传统的遍历:太罗嗦

/*
    使用传统的方式,遍历集合,对集合中的数据进行过滤
 */
public class Demo01List {
    public static void main(String[] args) {
        //创建一个List集合,存储姓名
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");

        //对list集合中的元素进行过滤,只要以张开头的元素,存储到一个新的集合中
        List<String> listA = new ArrayList<>();
        for(String s : list){
            if(s.startsWith("张")){
                listA.add(s);
            }
        }

        //对listA集合进行过滤,只要姓名长度为3的人,存储到一个新集合中
        List<String> listB = new ArrayList<>();
        for (String s : listA) {
            if(s.length()==3){
                listB.add(s);
            }
        }

        //遍历listB集合
        for (String s : listB) {
            System.out.println(s);
        }
    }
}

2.Stream流:简化

public class Demo02Stream {
    public static void main(String[] args) {
        //创建一个List集合,存储姓名
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        
        /*stream流中有个过滤方法叫做filter,filter这个方法的的参数是predicate,
        predicate是个函数式接口用于判断,所以我们可以用Lambda表达式*
        stream流中有个forEach方法,里面的参数是Consumer函数式接口*/
        list.stream()
                .filter(name -> name.startsWith("张")) //对list集合中的元素进行过滤,只要以张开头的元素
                .filter(name -> name.length() == 3) //对list集合进行过滤,只要姓名长度为3的人
                .forEach(name -> System.out.println(name)); //遍历list集合

    }
}

二、Stream流的使用

1.两种获取Stream流的方式

java.util.stream.Stream<T>是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
    - 所有的Collection集合都可以通过stream默认方法获取流;
        default Stream<E> stream​()
    - Stream接口的静态方法of可以获取数组对应的流。
        static <T> Stream<T> of​(T... values)
        参数是一个可变参数,那么我们就可以传递一个数组
public class Demo01GetStream {
    public static void main(String[] args) {
        //List的Stream流
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();
-----------------------------------------------------------------------------
        //set的stream流
        Set<String> set = new HashSet<>();
        Stream<String> stream2 = set.stream();
-----------------------------------------------------------------------------
        //map的stream流
        Map<String,String> map = new HashMap<>();
        Set<String> keySet = map.keySet();//map集合要先获取键,存储到一个Set集合中
        Stream<String> stream3 = keySet.stream();
        
        Collection<String> values = map.values();
        Stream<String> stream4 = values.stream();

        //获取键值对(键与值的映射关系 entrySet)
        Set<Map.Entry<String, String>> entries = map.entrySet();
        Stream<Map.Entry<String, String>> stream5 = entries.stream();
-----------------------------------------------------------------------------
        //把数组转换为Stream流
        Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);

        Integer[] arr = {1,2,3,4,5};
        Stream<Integer> stream7 = Stream.of(arr);
        
        String[] arr2 = {"a","bb","ccc"};
        Stream<String> stream8 = Stream.of(arr2);
-----------------------------------------------------------------------------        
    }
}

2.Stream流中常用的方法

stream流跟Scala的RDD编程思想一样,有转换算子和行动算子,“转换”是会把每个行为记录下来但并不会真的对它进行计算,“行动”才会将那些操作进行批量运算。而stream的行动算子又是“终结方法”有“count”方法 和 “forEach”,filter是一个管道流,只能被使用一次,也就是只能被一个行动算子执行一次
1.forEach方法

    Stream流中的常用方法_forEach
    void forEach(Consumer<? super T> action);
    该方法接收一个Consumer接口函数,会将每一个流元素交给该函数进行处理。
    Consumer接口是一个消费型的函数式接口,函数式接口就可以用Lambda表达式,消费数据

    简单记:
        forEach方法,用来遍历流中的数据
        是一个终结方法,遍历之后就不能继续调用Stream流中的其他方法
public class Demo02Stream_forEach {
    public static void main(String[] args) {

        Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
        
        //使用Stream流中的方法forEach对Stream流中的数据进行遍历
        stream.forEach((String name)->{
            System.out.println(name);
        });

        stream.forEach(name->System.out.println(name));
    }
}

2.filter方法

    Stream流中的常用方法_filter:用于对Stream流中的数据进行过滤
    Stream<T> filter(Predicate<? super T> predicate);
    filter方法的参数Predicate是一个函数式接口,所以可以传递Lambda表达式,对数据进行过滤
    Predicate中的抽象方法:
        boolean test(T t);
public class Demo03Stream_filter {
    public static void main(String[] args) {

        Stream<String> stream = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");

        //对Stream流中的元素进行过滤,只要姓张的人
        Stream<String> stream2 = stream.filter((String name)->{return name.startsWith("张");});

        //遍历stream2流
        stream2.forEach(name-> System.out.println(name));

        /*
            Stream流属于管道流,只能被消费(使用)一次
            第一个Stream流调用完毕方法,数据就会流转到下一个Stream上
            而这时第一个Stream流已经使用完毕,就会关闭了
            所以第一个Stream流就不能再调用方法了
            IllegalStateException: stream has already been operated upon or closed
         */
        //遍历stream流
        stream.forEach(name-> System.out.println(name));//报错,stream流只能使用一次
    }
}

3.map方法

    Stream流中的常用方法_map:用于类型转换(如果需要将流中的元素映射到另一个流中,可以使用map方法.<R> Stream<R> map(Function<? super T, ? extends R> mapper);
    该接口需要一个Function函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
    Function中的抽象方法:
        R apply(T t);
public class Demo04Stream_map {
    public static void main(String[] args) {

        Stream<String> stream = Stream.of("1", "2", "3", "4");
        
        //使用map方法,把字符串类型的整数,转换(映射)为Integer类型的整数
        Stream<Integer> stream2 = stream.map((String s)->{
            return Integer.parseInt(s);
        });
        
        stream2.forEach(i-> System.out.println(i));
    }
}

4.count方法

    Stream流中的常用方法_count:用于统计Stream流中元素的个数
    long count();
    count方法是一个终结方法,返回值是一个long类型的整数
    所以不能再继续调用Stream流中的其他方法了
public class Demo05Stream_count {
    public static void main(String[] args) {
        //获取一个Stream流
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        
        Stream<Integer> stream = list.stream();
        long count = stream.count();
        System.out.println(count);//7
    }
}

5.limit方法

    Stream流中的常用方法_limit:用于截取流中的元素
    limit方法可以对流进行截取,只取用前n个。方法签名:
    Stream<T> limit(long maxSize);
        参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作
    limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法
public class Demo06Stream_limit {
    public static void main(String[] args) {

        String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
        Stream<String> stream = Stream.of(arr);
        
        //使用limit对Stream流中的元素进行截取,只要前3个元素,返回一个新的流
        Stream<String> stream2 = stream.limit(3);

        stream2.forEach(name-> System.out.println(name));
    }
}

6.skip方法

    Stream流中的常用方法_skip:用于跳过元素
    如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流:
    Stream<T> skip(long n);
        如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
public class Demo07Stream_skip {
    public static void main(String[] args) {

        String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
        Stream<String> stream = Stream.of(arr);
        
        //使用skip方法跳过前3个元素,返回一个只含灰太狼和红太狼的新的流
        Stream<String> stream2 = stream.skip(3);

        stream2.forEach(name-> System.out.println(name));
    }
}

7.concat方法
和上面的普通方法不同的是,这是一个静态方法,类名Stream直接调用!!!

    Stream流中的常用方法_concat:用于把流组合到一起
    如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat
    static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
public class Demo08Stream_concat {
    public static void main(String[] args) {
        //创建一个Stream流
        Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
        //获取一个Stream2流
        String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
        Stream<String> stream2 = Stream.of(arr);
        
        //把以上两个流组合为一个流
        Stream<String> concat = Stream.concat(stream1, stream2);
        //遍历concat流
        concat.forEach(name-> System.out.println(name));
    }
}

三、小练习

    练习:集合元素处理(传统方式)
        现在有两个ArrayList集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以下若干操作步骤:
        1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
        2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
        3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
        4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
        5. 将两个队伍合并为一个队伍;存储到一个新集合中。
        6. 根据姓名创建Person对象;存储到一个新集合中。
        7. 打印整个队伍的Person对象信息。

传统的方法:

public class Person {
    private String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


public class Demo01StreamTest {
    public static void main(String[] args) {

        //第一支队伍
        ArrayList<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("宋远桥");
        one.add("苏星河");
        one.add("石破天");
        one.add("石中玉");
        one.add("老子");
        one.add("庄子");
        one.add("洪七公");
        //1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
        ArrayList<String> one1 = new ArrayList<>();
        for (String name : one) {
            if(name.length()==3){
                one1.add(name);
            }
        }
        //2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
        ArrayList<String> one2 = new ArrayList<>();
        for (int i = 0; i <3 ; i++) {
            one2.add(one1.get(i));//i = 0,1,2
        }

        //第二支队伍
        ArrayList<String> two = new ArrayList<>();
        two.add("古力娜扎");
        two.add("张无忌");
        two.add("赵丽颖");
        two.add("张三丰");
        two.add("尼古拉斯赵四");
        two.add("张天爱");
        two.add("张二狗");
        //3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
        ArrayList<String> two1 = new ArrayList<>();
        for (String name : two) {
            if(name.startsWith("张")){
                two1.add(name);
            }
        }
        //4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
        ArrayList<String> two2 = new ArrayList<>();
        for (int i = 2; i <two1.size() ; i++) {
            two2.add(two1.get(i)); //i 不包含0 1
        }

        //5. 将两个队伍合并为一个队伍;存储到一个新集合中。
        ArrayList<String> all = new ArrayList<>();
        all.addAll(one2);
        all.addAll(two2);

        //6. 根据姓名创建Person对象;存储到一个新集合中。
        ArrayList<Person> list = new ArrayList<>();
        for (String name : all) {
            list.add(new Person(name));
        }

        //7. 打印整个队伍的Person对象信息。
        for (Person person : list) {
            System.out.println(person);
        }
    }
}

Stream流的方法:

public class Person {
    private String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


public class Demo02StreamTest {
    public static void main(String[] args) {
        
        //第一支队伍
        ArrayList<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("宋远桥");
        one.add("苏星河");
        one.add("石破天");
        one.add("石中玉");
        one.add("老子");
        one.add("庄子");
        one.add("洪七公");
        //1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
        //2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
        Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);

        
        //第二支队伍
        ArrayList<String> two = new ArrayList<>();
        two.add("古力娜扎");
        two.add("张无忌");
        two.add("赵丽颖");
        two.add("张三丰");
        two.add("尼古拉斯赵四");
        two.add("张天爱");
        two.add("张二狗");
        //3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
        //4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
        Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张")).skip(2);

        
        //5. 将两个队伍合并为一个队伍;存储到一个新集合中。
        //6. 根据姓名创建Person对象;存储到一个新集合中。
        //7. 打印整个队伍的Person对象信息。
        Stream.concat(oneStream,twoStream).map(name->new Person(name)).forEach(p-> System.out.println(p));
    }
}

欢迎纠错和指导,感谢浏览和收藏

int HTTPSessionExecute(TPHTTPSERVERSESSION *pSession) { int iRet, iGot; unsigned long long ullCurTime = tpgetboottime(); pSession->reply_error_code = 0; RETURN_IVALID_IF(!pSession) /* 非P2P方式拉且在规定时间内未完成HTTP的完整消息交互,则断开 */ if ((pSession->p2p_connection == NULL) && (pSession->iSessionState != TPHTTP_SESSION_STATE_PLAYING)) { if (pSession->ulTime4LastHTTPMsg == 0) { pSession->ulTime4LastHTTPMsg = ullCurTime; } if ((ullCurTime - pSession->ulTime4LastHTTPMsg) > pSession->ullRecvTimeout) { HTTP_ERROR("HTTP: session timeout"); return(TPHTTPSERVER_EC_RTP_FAILURE); } } if((eConnType_Relay == pSession->conn_type) && (TPHTTP_SESSION_STATE_INIT == pSession->iSessionState)) {/* relay的init状态才判断是否需要发送心跳包 */ HTTPRelayPreHeatBeat(pSession, (S32)(ullCurTime/1000)); } /* p2p方式拉,先判断UDT的状态,UDT状态异常则返回 TPRTSPSERVER_EC_SOCKET_CLOSE */ if(pSession->p2p_connection != NULL) { int udt_state = P2PUdt_GetState(pSession->p2p_connection); if(udt_state != CONNECTING && udt_state != CONNECTED) { HTTP_ERROR_LOG("[p2p dbg] UDT state(%d)", udt_state); return TPRTSPSERVER_EC_SOCKET_CLOSE; } else if (udt_state == CONNECTING) { /*如果为connecting状态,则判断是否超时*/ if ((ullCurTime - pSession->startconnectTime) > P2P_UDT_SETUP_TIMEOUT) { HTTP_ERROR_LOG("[p2p dbg] UDT connecting time out"); return TPRTSPSERVER_EC_SOCKET_CLOSE; } } } //没有正在发送的http报文,则尝试发送响应信令/通知数据 if (!HttpStreamCtx_IsSendPending(&pSession->stream_ctx)) { HttpSession_TrySendReplyData(pSession); } /* 直接推功能:根据字段及连接类型 */ if (pSession->is_directly_push_stream && pSession->conn_type == eConnType_Relay) { /* 直接推:将填充拉参数,跳到取处*/ pSession->is_directly_push_stream = 0; pSession->iSessionStream = HTTP_STREAM_PREVIEW; /* 监听客户端预览拉请求 */ PREVIEW_STREAM_TYPE_MSG msg = {0}; msg.type = HTTP_STREAM_PREVIEW; msg_send(PREVIEW_HTTP_STREAM_MID, (uint8_t *)&msg, sizeof(PREVIEW_STREAM_TYPE_MSG)); /* 数限制判断: 若码数已达上限,不直接推 */ int is_up_to_limit = SessionStream_IsUpToLimit(pSession->iCurStreamID, pSession->iSessionStream); if (is_up_to_limit) { HTTPSession_SetState(pSession, TPHTTP_SESSION_STATE_INIT); } else { HTTPSession_SetState(pSession, TPHTTP_SESSION_STATE_READY); HttpStreamCtx_Init(&pSession->stream_ctx, pSession->iSessionStream, pSession->uSessionID, 0, 0, pSession); goto Push_Stream_Handle; } } iGot = HTTPSessionRecv(pSession); if ((TP_TCP_EC_FAILURE == iGot) || (TP_TCP_EC_SOCKET_CLOSE == iGot) || (iGot == TP_TCP_EC_BUFF_FULL)) { HTTP_ERROR_LOG("HTTP: iGot=%d", iGot); if(TPHTTP_SESSION_STATE_PLAYING == pSession->iSessionState && HTTP_STREAM_TALK == pSession->iSessionStream) { TALK_MASK_RELOAD_MSG msg = {0}; msg.enabled = 0; msg_send(TALK_MASK_RELOAD, (uint8_t *)&msg, sizeof(TALK_MASK_RELOAD_MSG)); } return(TPHTTPSERVER_EC_FAILURE); } /* relay首个报文为boundary */ if (pSession->conn_type == eConnType_Relay && pSession->is_relay_boundary_msg) { return HTTPHandleRelayBoundaryMsg(pSession); } if ((iGot > 0) || (MBUFFERByteArrayCurPos(&pSession->RXBuffer) > 0 && pSession->iSessionParseState != HTTP_EC_NEED_MORE_DATA)) { iRet = HTTPSessionParse(pSession); if (iRet == TPHTTPSERVER_EC_FAILURE) { HTTP_ERROR_LOG("Session %d recv invalid HTTP Msg", pSession->iSessionID); if (pSession->conn_type != eConnType_Relay) { HTTPSessionReplyBadRequest(pSession); } /* 消息错误,清空接收缓存数据 */ MBUFFERByteArrayReset(&pSession->RXBuffer); return (TPHTTPSERVER_EC_OK); } else if (iRet == HTTP_EC_NEED_MORE_DATA) { return (TPHTTPSERVER_EC_OK); } /* 未知的消息类型,或者是RTCP报文,更新心跳,忽略后续解析 */ if (pSession->Method.iMethod == HTTP_UN_SUPPORT) { pSession->ulTime4LastHTTPMsg = ullCurTime; return (TPHTTPSERVER_EC_OK); } pSession->ulTime4LastHTTPMsg = ullCurTime; switch (pSession->Method.iMethod) { case HTTP_POST: HTTP_DEBUG("Session %d receive POST, current state %d", pSession->iSessionID, pSession->iSessionState); if (pSession->iSessionState == TPHTTP_SESSION_STATE_READY) { int is_up_to_limit = SessionStream_IsUpToLimit(pSession->iCurStreamID, pSession->iSessionStream); if (is_up_to_limit) { #ifdef INAPP_DIAGNOSE /* 若主子码都满了诊断将无法进入playing,则在此处将数情况通知diagnose模块,同时还原相关变量 */ if (eStreamDiagnose_ON == pSession->diag_mode && SessionStream_IsUpToLimit(TPRTP_STREAM_ID_MAIN, HTTP_STREAM_PREVIEW) && SessionStream_IsUpToLimit(TPRTP_STREAM_ID_SUB, HTTP_STREAM_PREVIEW)) { diagnose_reply_bitrate(pSession->conn_type, pSession->bitrate, IPC_DIAGNOSE_STREAM_FULL); pSession->diag_mode = eStreamDiagnose_INIT; pSession->diag_start_time = 0; pSession->trans_byte_total = 0; pSession->bitrate = 0; } #endif int reply_code = TPPLAYER_SESSION_UP_TO_LIMIT; #ifdef DOORBELL_FUNCTION_SUPPORT if (HTTP_STREAM_TALK != pSession->iSessionStream || ERROR == srtp_session_free_talk()) #endif { if (HTTP_STREAM_TALK == pSession->iSessionStream) { reply_code = TPPLAYER_EC_AUDIO_DEVICE_BUSY; } pSession->reply_error_code = reply_code; iRet = HTTPSessionReplyPOST(pSession); if (iRet != TPHTTPSERVER_EC_OK) { return(TPHTTPSERVER_EC_FAILURE); } HTTPSession_SetState(pSession, TPHTTP_SESSION_STATE_INIT); return TPHTTPSERVER_EC_OK; } } if (pSession->iSessionStream == HTTP_STREAM_PLAYBACK || pSession->iSessionStream == HTTP_STREAM_DOWNLOAD || pSession->iSessionStream == HTTP_STREAM_RECORD_DOWNLOAD) { /* 回放/下载录像/下载缩略图信令,若sd卡状态异常(不可用),则在回复中带上sd卡状态信息 */ if (!is_sd_card_available()) { pSession->reply_error_code = TPPLAYER_EC_STORAGE_UNAVAILABLE; iRet = HTTPSessionReplyPOST(pSession); if (iRet != TPHTTPSERVER_EC_OK) { return(TPHTTPSERVER_EC_FAILURE); } HTTPSession_SetState(pSession, TPHTTP_SESSION_STATE_INIT); return TPHTTPSERVER_EC_OK; } } #ifdef TAPO_USR_DEF_AUDIO_UPLOAD if (HTTP_STREAM_USR_DEF_AUDIO == pSession->iSessionStream) { if (pSession->file_ops.fd < 0) { int reply_code = 0; switch (pSession->file_ops.fd) { case USR_DEF_AUDIO_FILE_ID_FULL_FD: reply_code = TPPLAYER_EC_USR_DEF_AUDIO_FULL; break; case USR_DEF_AUDIO_DEVICE_BUSY_FD: reply_code = TPPLAYER_EC_AUDIO_DEVICE_BUSY; break; case USR_DEF_AUDIO_NAME_DUPLICATE_FD: reply_code = TPPLAYER_EC_NAME_DUPLICATE; break; default: break; } pSession->reply_error_code = reply_code; iRet = HTTPSessionReplyPOST(pSession); if (iRet != TPHTTPSERVER_EC_OK) { return (TPHTTPSERVER_EC_FAILURE); } HTTPSession_SetState(pSession, TPHTTP_SESSION_STATE_INIT); return TPHTTPSERVER_EC_OK; } } #endif } iRet = HTTPSessionReplyPOST(pSession); if (iRet != TPHTTPSERVER_EC_OK) { return(TPHTTPSERVER_EC_FAILURE); } //HTTP_DEBUG("Session %d receive SETUP, current state %d", pSession->iSessionID, pSession->iSessionState); if (pSession->iSessionState == TPHTTP_SESSION_STATE_READY) { if (pSession->iSessionStream == HTTP_STREAM_DOWNLOAD || pSession->iSessionStream == HTTP_STREAM_REALTIME_PHOTO_DOWNLOAD) { TPSendDownloadData(pSession); return(TPHTTPSERVER_EC_OK); } #ifdef SPLENDID_MOMENT else if (pSession->iSessionStream == HTTP_STREAM_SPLMOM_DOWNLOAD) { TPSendSplendidMomentData(pSession); return(TPHTTPSERVER_EC_OK); } #endif #ifdef DETECTION_FSS_SUPPORT if (pSession->iSessionStream == HTTP_STREAM_GET_FACE) { if (pSession->face_info.all_trans_finish == FALSE && pSession->face_info.image_status_check_finish == IMG_CHECK_DONE) { if( pSession->face_info.trans_num < pSession->face_info.count && pSession->face_info.face_items[pSession->face_info.trans_num].trans_status == IMG_TRANS_SEND_PROCESSING) { TPSendFaceimgData(pSession,pSession->face_info.face_items[pSession->face_info.trans_num].face_id); } else { //当前列表请求的图片全部发完后,face_id=0,发送finished TPSendFaceimgData(pSession, 0); } } return(TPHTTPSERVER_EC_OK); } #endif Push_Stream_Handle: if (pSession->iSessionStream == HTTP_STREAM_PREVIEW) { if (pSession->iStreamType == TPRTP_STREAM_TYPE_VIDEO_MAIN #ifdef DUAL_CAM || pSession->iStreamType == TPRTP_STREAM_TYPE_VIDEO_MAIN2 #endif ) { pSession->video_desc.priv = (void *)pSession; pSession->video_desc.stream_id = get_http_main_stream_id(); #ifdef DUAL_CAM if (pSession->iStreamType == TPRTP_STREAM_TYPE_VIDEO_MAIN2) { pSession->video_desc.stream_id = get_http_main2_stream_id(); } else { pSession->video2_desc.priv = (void *)pSession; pSession->video2_desc.stream_id = get_http_main2_stream_id(); pSession->video2_desc.stream_ctx = &pSession->stream_ctx; pSession->video2_desc.stream_ctx->session_ctx = (void *)pSession; trans_attach_to_stream(&pSession->video2_desc, NULL); } #endif pSession->video_desc.stream_ctx = &pSession->stream_ctx; pSession->video_desc.stream_ctx->session_ctx = (void *)pSession; trans_attach_to_stream(&pSession->video_desc, NULL); } else { S32 stream_video_id; #ifdef DUAL_CAM if (pSession->iStreamType == TPRTP_STREAM_TYPE_VIDEO_MINOR2) stream_video_id = trans_register_stream_http(AVDM_TYPE_MINOR2, NULL, NULL); else #endif stream_video_id = trans_register_stream_http(AVDM_TYPE_SUB, NULL, NULL); if(stream_video_id == -1) { HTTP_ERROR_LOG("attach stream fail"); return (TPHTTPSERVER_EC_FAILURE); } pSession->video_desc.priv = (void *)pSession; pSession->video_desc.stream_id = stream_video_id; pSession->video_desc.stream_ctx = &pSession->stream_ctx; pSession->video_desc.stream_ctx->session_ctx = (void *)pSession; trans_attach_to_stream(&pSession->video_desc, NULL); #ifdef DUAL_CAM if (pSession->iStreamType == TPRTP_STREAM_TYPE_VIDEO_MINOR) // DC_TODO 根据streams判断 { stream_video_id = trans_register_stream_http(AVDM_TYPE_MINOR2, NULL, NULL); pSession->video2_desc.priv = (void *)pSession; pSession->video2_desc.stream_id = stream_video_id; pSession->video2_desc.stream_ctx = &pSession->stream_ctx; pSession->video2_desc.stream_ctx->session_ctx = (void *)pSession; trans_attach_to_stream(&pSession->video2_desc, NULL); } #endif } { pSession->audio_desc.priv = (void *)pSession; pSession->audio_desc.stream_id = get_http_audio_stream_id(); pSession->audio_desc.stream_ctx = &pSession->stream_ctx; pSession->audio_desc.stream_ctx->session_ctx = (void *)pSession; trans_attach_to_stream(&pSession->audio_desc, NULL); } } #ifdef DOORBELL_FUNCTION_SUPPORT else if (pSession->iSessionStream == HTTP_STREAM_AUDIO_ONLY) { pSession->audio_desc.priv = (void *)pSession; pSession->audio_desc.stream_id = get_http_audio_stream_id(); pSession->audio_desc.stream_ctx = &pSession->stream_ctx; pSession->audio_desc.stream_ctx->session_ctx = (void *)pSession; trans_attach_to_stream(&pSession->audio_desc, NULL); } #endif else if (pSession->iSessionStream == HTTP_STREAM_PLAYBACK && NULL == pSession->video_desc.priv) { { S32 stream_id; trans_attach_param_t attach_param; attach_param.version = pSession->playback_ver; if (pSession->playback_ver == PLAYBACK_VERSION_WITH_PLAYER_ID) { attach_param.data = (void *)pSession->player_id; } else { attach_param.data = (void *)&pSession->client_id; } stream_id = trans_register_stream_http(TRANS_STREAM_TYPE_PLAYBACK, NULL, &attach_param); if(stream_id == -1) { HTTP_ERROR_LOG("attach stream fail"); return (TPHTTPSERVER_EC_FAILURE); } pSession->video_desc.priv = (void *)pSession; pSession->video_desc.stream_id = stream_id; pSession->video_desc.stream_ctx = &pSession->stream_ctx; pSession->video_desc.stream_ctx->session_ctx = (void *)pSession; trans_attach_to_stream(&pSession->video_desc, NULL); } } else if (pSession->iSessionStream == HTTP_STREAM_RECORD_DOWNLOAD && NULL == pSession->video_desc.priv) { { S32 stream_id; trans_attach_param_t attach_param; attach_param.version = pSession->playback_ver; if (pSession->playback_ver == PLAYBACK_VERSION_WITH_PLAYER_ID) { attach_param.data = (void *)pSession->player_id; } else { attach_param.data = (void *)&pSession->client_id; } stream_id = trans_register_stream_http(TRANS_STREAM_TYPE_RECORD_DOWNLOAD, NULL, &attach_param); if(stream_id == -1) { HTTP_ERROR("attach stream fail"); return (TPHTTPSERVER_EC_FAILURE); } pSession->video_desc.priv = (void *)pSession; pSession->video_desc.stream_id = stream_id; pSession->video_desc.stream_ctx = &pSession->stream_ctx; pSession->video_desc.stream_ctx->session_ctx = (void *)pSession; trans_attach_to_stream(&pSession->video_desc, NULL); } } //HTTP_DEBUG("Session: %d receive PLAY, current state %d", pSession->iSessionID, pSession->iSessionState); pSession->video_desc.param.start_time = (pSession->npt == -1 || pSession->npt == 0) ? pSession->start_time : pSession->npt; pSession->video_desc.param.timestamp = pSession->timestamp; pSession->video_desc.param.change_day = pSession->change_day; if(TPHTTP_SESSION_STATE_PAUSE == pSession->iSessionState && pSession->npt == -1) pSession->video_desc.param.start_time = -1; pSession->video_desc.param.client_id = pSession->video_desc.stream_id; if(pSession->scale - 1 > 0.0) { pSession->video_desc.param.scale.denominator = 1; //默认倍速为1 pSession->video_desc.param.scale.numerator = pSession->scale; } else { pSession->video_desc.param.scale.denominator = 1 / pSession->scale; //默认倍速为1 pSession->video_desc.param.scale.numerator = 1; } pSession->video_desc.param.is_end = 0; pSession->video_desc.param.type_bitmap = 1; pSession->video_desc.param.task_type = 1; pSession->video_desc.param.type_bitmap = 6; #ifdef DUAL_CAM //HTTP_DEBUG("Session: %d receive PLAY, current state %d", pSession->iSessionID, pSession->iSessionState); pSession->video2_desc.param.start_time = (pSession->npt == -1 || pSession->npt == 0) ? pSession->start_time : pSession->npt; pSession->video2_desc.param.timestamp = pSession->timestamp; pSession->video2_desc.param.change_day = pSession->change_day; if(TPHTTP_SESSION_STATE_PAUSE == pSession->iSessionState && pSession->npt == -1) pSession->video2_desc.param.start_time = -1; pSession->video2_desc.param.client_id = pSession->video2_desc.stream_id; if(pSession->scale - 1 > 0.0) { pSession->video2_desc.param.scale.denominator = 1; //默认倍速为1 pSession->video2_desc.param.scale.numerator = pSession->scale; } else { pSession->video2_desc.param.scale.denominator = 1 / pSession->scale; //默认倍速为1 pSession->video2_desc.param.scale.numerator = 1; } pSession->video2_desc.param.is_end = 0; pSession->video2_desc.param.type_bitmap = 1; pSession->video2_desc.param.task_type = 1; pSession->video2_desc.param.type_bitmap = 6; #endif if (pSession->iSessionStream == HTTP_STREAM_PLAYBACK) { pSession->video_desc.param.vod_type = pSession->vod_type; pSession->video_desc.param.auto_seek = pSession->auto_seek; pSession->video_desc.param.auto_switch_date = pSession->auto_switch_date; pSession->vod_type = 0; pSession->auto_seek = 0; } if (pSession->iSessionStream == HTTP_STREAM_RECORD_DOWNLOAD) { pSession->video_desc.param.end_time = pSession->end_time; //录像下载需要传入结束时间 pSession->video_desc.param.task_type = 2; //录像下载的task_type为2 trans_start_download(&pSession->video_desc); } else { trans_start_play(&pSession->video_desc); #ifdef DUAL_CAM trans_start_play(&pSession->video2_desc); #endif } if (pSession->web_connection != NULL) { pSession->webparam->if_attach = 1; } #ifndef HOMEKIT_ONBOARDING_SUPPORT SessionAllowConnection(pSession->iCurStreamID, pSession->iSessionStream); #else /* 如果添加一路直播 */ if (SessionAllowConnection(pSession->iCurStreamID, pSession->iSessionStream) && pSession->iSessionStream == HTTP_STREAM_PREVIEW) { g_http_stream_count++; LED_TRIGGER_MSG led_trigger; memset(&led_trigger, 0, sizeof(led_trigger)); led_trigger.trigger_mask = LED_TRIGGER_START_GENMASK(LED_TRIGGER_TYPE_TAPO_STREAMING); msg_send(LED_HOMEKIT_TRIGGER_MID, (U8 *)&led_trigger, sizeof(led_trigger)); } #endif if(HTTP_STREAM_TALK == pSession->iSessionStream) { TALK_MASK_RELOAD_MSG msg = {0}; msg.enabled = 1; msg_send(TALK_MASK_RELOAD, (uint8_t *)&msg, sizeof(TALK_MASK_RELOAD_MSG)); } HTTPSession_SetState(pSession, TPHTTP_SESSION_STATE_PLAYING); #if defined(TELEMETRY_SUPPORT) pSession->conn_start_time = nvmp_get_us(); #endif } if (pSession->bIsSessionON == 0) { HTTP_ERROR("Setup exit During CloseSession %d", pSession->iSessionID); return TPHTTPSERVER_EC_STATE_NONFATAL; } break; default: HTTP_INFO_LOG("TPHTTPSERVER_EC_FAILURE"); return (TPHTTPSERVER_EC_FAILURE); } } else if(TP_TCP_EC_WAIT == iGot) { return TPHTTPSERVER_EC_GOTNOTING; } return(TPHTTPSERVER_EC_OK); } 解释代码,详细一点
最新发布
10-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BlackTurn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值