int SrsRtmpConn::playing(SrsSource* source) { int ret = ERROR_SUCCESS; if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_play(req->vhost))) != ERROR_SUCCESS) { srs_error("check play_refer failed. ret=%d", ret); return ret; } srs_verbose("check play_refer success."); SrsConsumer* consumer = NULL; if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) { srs_error("create consumer failed. ret=%d", ret); return ret; } srs_assert(consumer != NULL); SrsAutoFree(SrsConsumer, consumer, false); srs_verbose("consumer created success."); rtmp->set_recv_timeout(SRS_PULSE_TIMEOUT_US); SrsPithyPrint pithy_print(SRS_STAGE_PLAY_USER); int64_t starttime = -1; while (true) { // switch to other st-threads. st_usleep(0); pithy_print.elapse(); // read from client. int ctl_msg_ret = ERROR_SUCCESS; if (true) { SrsMessage* msg = NULL; ctl_msg_ret = ret = rtmp->recv_message(&msg); srs_verbose("play loop recv message. ret=%d", ret); if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { srs_error("recv client control message failed. ret=%d", ret); } return ret; } if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) { if (!srs_is_system_control_error(ret)) { srs_error("process play control message failed. ret=%d", ret); } return ret; } } // get messages from consumer. SrsSharedPtrMessage** msgs = NULL; int count = 0; if ((ret = consumer->get_packets(0, msgs, count)) != ERROR_SUCCESS) { srs_error("get messages from consumer failed. ret=%d", ret); return ret; } // reportable if (pithy_print.can_print()) { srs_trace("-> "SRS_LOG_ID_PLAY " time=%"PRId64", duration=%"PRId64", cmr=%d, msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", pithy_print.age(), duration, ctl_msg_ret, count, rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps()); } if (count <= 0) { srs_verbose("no packets in queue."); continue; } SrsAutoFree(SrsSharedPtrMessage*, msgs, true); // sendout messages for (int i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs[i]; // the send_message will free the msg, // so set the msgs[i] to NULL. msgs[i] = NULL; srs_assert(msg); // foreach msg, collect the duration. // @remark: never use msg when sent it, for the protocol sdk will free it. if (starttime < 0 || starttime > msg->header.timestamp) { starttime = msg->header.timestamp; } duration += msg->header.timestamp - starttime; starttime = msg->header.timestamp; if ((ret = rtmp->send_and_free_message(msg)) != ERROR_SUCCESS) { srs_error("send message to client failed. ret=%d", ret); return ret; } } // if duration specified, and exceed it, stop play live. // @see: https://github.com/winlinvip/simple-rtmp-server/issues/45 if (req->duration > 0 && duration >= (int64_t)req->duration) { ret = ERROR_RTMP_DURATION_EXCEED; srs_trace("stop live for duration exceed. ret=%d", ret); return ret; } } return ret; }
int SrsRtmpConn::playing(SrsSource* source) { int ret = ERROR_SUCCESS; if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_play(req->vhost))) != ERROR_SUCCESS) { srs_error("check play_refer failed. ret=%d", ret); return ret; } srs_verbose("check play_refer success."); SrsConsumer* consumer = NULL; if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) { srs_error("create consumer failed. ret=%d", ret); return ret; } srs_assert(consumer != NULL); SrsAutoFree(SrsConsumer, consumer, false); srs_verbose("consumer created success."); rtmp->set_recv_timeout(SRS_PULSE_TIMEOUT_US); SrsPithyPrint pithy_print(SRS_STAGE_PLAY_USER); while (true) { pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000); // switch to other st-threads. st_usleep(0); // read from client. int ctl_msg_ret = ERROR_SUCCESS; if (true) { SrsCommonMessage* msg = NULL; ctl_msg_ret = ret = rtmp->recv_message(&msg); srs_verbose("play loop recv message. ret=%d", ret); if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { srs_error("recv client control message failed. ret=%d", ret); } return ret; } if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) { if (!srs_is_system_control_error(ret)) { srs_error("process play control message failed. ret=%d", ret); } return ret; } } // get messages from consumer. SrsSharedPtrMessage** msgs = NULL; int count = 0; if ((ret = consumer->get_packets(0, msgs, count)) != ERROR_SUCCESS) { srs_error("get messages from consumer failed. ret=%d", ret); return ret; } // reportable if (pithy_print.can_print()) { srs_trace("-> time=%"PRId64", cmr=%d, msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", pithy_print.get_age(), ctl_msg_ret, count, rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps()); } if (count <= 0) { srs_verbose("no packets in queue."); continue; } SrsAutoFree(SrsSharedPtrMessage*, msgs, true); // sendout messages for (int i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs[i]; // the send_message will free the msg, // so set the msgs[i] to NULL. msgs[i] = NULL; if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { srs_error("send message to client failed. ret=%d", ret); return ret; } } } return ret; }