// Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "flow.h" #include #include #include #ifndef _RTSP_SERVER_HH #include #endif #if !defined(LIVE555_SERVER_H264) && !defined(LIVE555_SERVER_H265) #error "This RTSP !VIDEO! implementation currently only support at least one of h264 and h265!!!" #endif #ifdef LIVE555_SERVER_H264 #include "h264_server_media_subsession.hh" #endif #ifdef LIVE555_SERVER_H265 #include "h265_server_media_subsession.hh" #endif #include "aac_server_media_subsession.hh" #include "live555_media_input.hh" #include "live555_server.hh" #include "mjpeg_server_media_subsession.hh" #include "mp2_server_media_subsession.hh" #include "simple_server_media_subsession.hh" #include "buffer.h" #include "codec.h" #include "media_config.h" #include "media_reflector.h" #include "media_type.h" namespace easymedia { static bool SendMediaToServer(Flow* f, MediaBufferVector& input_vector); class RtspServerFlow : public Flow { public: RtspServerFlow(const char* param); virtual ~RtspServerFlow(); static const char* GetFlowName() { return "live555_rtsp_server"; } private: Live555MediaInput* server_input; std::shared_ptr rtspConnection; std::string channel_name; std::string video_type; std::string audio_type; friend bool SendMediaToServer(Flow* f, MediaBufferVector& input_vector); void CallPlayVideoHandler(); void CallPlayAudioHandler(); }; bool SendMediaToServer(Flow* f, MediaBufferVector& input_vector) { RtspServerFlow* rtsp_flow = (RtspServerFlow*)f; for (auto& buffer : input_vector) { if (!buffer) { continue; } if (buffer && buffer->IsHwBuffer()) { // hardware buffer is limited, copy it auto new_buffer = MediaBuffer::Clone(*buffer.get()); new_buffer->SetType(buffer->GetType()); buffer = new_buffer; } if ((buffer->GetUserFlag() & MediaBuffer::kIntra)) { std::list> spspps; if (rtsp_flow->video_type == VIDEO_H264) { spspps = split_h264_separate((const uint8_t*)buffer->GetPtr(), buffer->GetValidSize(), buffer->GetUSTimeStamp()); } else if (rtsp_flow->video_type == VIDEO_H265) { spspps = split_h265_separate((const uint8_t*)buffer->GetPtr(), buffer->GetValidSize(), buffer->GetUSTimeStamp()); } // Independently send vps, sps, pps packets to live555. for (auto& buf : spspps) { rtsp_flow->server_input->PushNewVideo(buf); } // The original Intr frame information is sent to live555. // At this time it still contains extra information. rtsp_flow->server_input->PushNewVideo(buffer); } else if (buffer->GetType() == Type::Audio) { rtsp_flow->server_input->PushNewAudio(buffer); } else if (buffer->GetType() == Type::Video) { rtsp_flow->server_input->PushNewVideo(buffer); } else { // muxer buffer rtsp_flow->server_input->PushNewMuxer(buffer); } } return true; } RtspServerFlow::RtspServerFlow(const char* param) { std::list input_data_types; std::map params; if (!parse_media_param_map(param, params)) { SetError(-EINVAL); return; } std::string value; CHECK_EMPTY_SETERRNO(value, params, KEY_INPUTDATATYPE, EINVAL) parse_media_param_list(value.c_str(), input_data_types, ','); CHECK_EMPTY_SETERRNO(channel_name, params, KEY_CHANNEL_NAME, EINVAL) value = params[KEY_PORT_NUM]; int port = std::stoi(value); std::string& username = params[KEY_USERNAME]; std::string& userpwd = params[KEY_USERPASSWORD]; rtspConnection = RtspConnection::getInstance(port, username, userpwd); int sample_rate = 0, channels = 0, profiles = 0; unsigned bitrate = 0; value = params[KEY_SAMPLE_RATE]; if (!value.empty()) { sample_rate = std::stoi(value); } value = params[KEY_CHANNELS]; if (!value.empty()) { channels = std::stoi(value); } value = params[KEY_PROFILE]; if (!value.empty()) { profiles = std::stoi(value); } value = params[KEY_SAMPLE_FMT]; if (!value.empty()) { bitrate = std::stoi(value); } if (rtspConnection) { int in_idx = 0; std::string markname; SlotMap sm; for (auto& type : input_data_types) { if (type == VIDEO_H264 || type == VIDEO_H265 || type == IMAGE_JPEG) { video_type = type; } else if (type == AUDIO_AAC || type == AUDIO_G711A || type == AUDIO_G711U || type == AUDIO_G726 || type == AUDIO_MP2 || type == MUXER_MPEG_TS || type == MUXER_MPEG_PS) { audio_type = type; } sm.input_slots.push_back(in_idx); in_idx++; } server_input = rtspConnection->createNewChannel(channel_name, video_type, audio_type, channels, sample_rate, bitrate, profiles); server_input->SetStartVideoStreamCallback(std::bind(&RtspServerFlow::CallPlayVideoHandler, this)); server_input->SetStartAudioStreamCallback(std::bind(&RtspServerFlow::CallPlayAudioHandler, this)); sm.process = SendMediaToServer; sm.thread_model = Model::ASYNCCOMMON; sm.mode_when_full = InputMode::BLOCKING; sm.input_maxcachenum.push_back(0); // no limit if (sm.input_slots.size() > 1) { sm.input_maxcachenum.push_back(0); } markname = "rtsp " + channel_name + std::to_string(in_idx); if (!InstallSlotMap(sm, markname, 0)) { LOG("Fail to InstallSlotMap, %s\n", markname.c_str()); goto err; } } else { goto err; } return; err: SetError(-EINVAL); } void RtspServerFlow::CallPlayVideoHandler() { auto handler = GetPlayVideoHandler(); if (handler != nullptr) { handler(this); } } void RtspServerFlow::CallPlayAudioHandler() { auto handler = GetPlayAudioHandler(); if (handler) { handler(this); } } RtspServerFlow::~RtspServerFlow() { AutoPrintLine apl(__func__); StopAllThread(); SetDisable(); if (rtspConnection) { rtspConnection->removeChannel(channel_name); } server_input = nullptr; } DEFINE_FLOW_FACTORY(RtspServerFlow, Flow) const char* FACTORY(RtspServerFlow)::ExpectedInputDataType() { return ""; } const char* FACTORY(RtspServerFlow)::OutPutDataType() { return ""; } } // namespace easymedia