本文主要是介绍srs rtmp转flv,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
SrsLiveStream 转换启动类
srs是通过SrsLiveStream来转换rtmp到flv,该类会判断http请求参数,根据后缀".flv"来开启
flv转换相关逻辑。
SrsLiveStream的实现如下:
// HTTP Live Streaming, to transmux RTMP to HTTP FLV or other format.
// TODO: FIXME: Rename to SrsHttpLive
class SrsLiveStream : public ISrsHttpHandler
{
private:SrsRequest* req;SrsLiveSource* source;SrsBufferCache* cache;
public:SrsLiveStream(SrsLiveSource* s, SrsRequest* r, SrsBufferCache* c);virtual ~SrsLiveStream();virtual srs_error_t update_auth(SrsLiveSource* s, SrsRequest* r);
public:virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
private:virtual srs_error_t do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);virtual srs_error_t http_hooks_on_play(ISrsHttpMessage* r);virtual void http_hooks_on_stop(ISrsHttpMessage* r);virtual srs_error_t streaming_send_messages(ISrsBufferEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs);
};
调用堆栈
srs!SrsFlvTransmuxer::write_tags(SrsSharedPtrMessage**, int) (/Users/changan1/working/program/srs/trunk/src/kernel/srs_kernel_flv.cpp:568)
srs!SrsFlvStreamEncoder::write_tags(SrsSharedPtrMessage**, int) (/Users/changan1/working/program/srs/trunk/src/app/srs_app_http_stream.cpp:380)
srs!SrsLiveStream::do_serve_http(ISrsHttpResponseWriter*, ISrsHttpMessage*) (/Users/changan1/working/program/srs/trunk/src/app/srs_app_http_stream.cpp:750)
srs!SrsLiveStream::serve_http(ISrsHttpResponseWriter*, ISrsHttpMessage*) (/Users/changan1/working/program/srs/trunk/src/app/srs_app_http_stream.cpp:602)
srs!SrsHttpServeMux::serve_http(ISrsHttpResponseWriter*, ISrsHttpMessage*) (/Users/changan1/working/program/srs/trunk/src/protocol/srs_protocol_http_stack.cpp:788)
srs!SrsHttpServer::serve_http(ISrsHttpResponseWriter*, ISrsHttpMessage*) (/Users/changan1/working/program/srs/trunk/src/app/srs_app_http_conn.cpp:571)
srs!SrsHttpAuthMux::serve_http(ISrsHttpResponseWriter*, ISrsHttpMessage*) (/Users/changan1/working/program/srs/trunk/src/protocol/srs_protocol_http_stack.cpp:977)
srs!SrsHttpCorsMux::serve_http(ISrsHttpResponseWriter*, ISrsHttpMessage*) (/Users/changan1/working/program/srs/trunk/src/protocol/srs_protocol_http_stack.cpp:944)
srs!SrsHttpConn::process_request(ISrsHttpResponseWriter*, ISrsHttpMessage*, int) (/Users/changan1/working/program/srs/trunk/src/app/srs_app_http_conn.cpp:258)
srs!SrsHttpConn::process_requests(SrsRequest**) (/Users/changan1/working/program/srs/trunk/src/app/srs_app_http_conn.cpp:211)
srs!SrsHttpConn::do_cycle() (/Users/changan1/working/program/srs/trunk/src/app/srs_app_http_conn.cpp:162)
srs!SrsHttpConn::cycle() (/Users/changan1/working/program/srs/trunk/src/app/srs_app_http_conn.cpp:107)
srs!SrsFastCoroutine::cycle() (/Users/changan1/working/program/srs/trunk/src/app/srs_app_st.cpp:285)
srs!SrsFastCoroutine::pfn(void*) (/Users/changan1/working/program/srs/trunk/src/app/srs_app_st.cpp:300)
srs!_st_thread_main (/Users/changan1/working/program/srs/trunk/objs/Platform-SRS5-Darwin-22.6.0-Clang15.0.0-x86_64/st-srs/sched.c:380)
srs!st_thread_create (/Users/changan1/working/program/srs/trunk/objs/Platform-SRS5-Darwin-22.6.0-Clang15.0.0-x86_64/st-srs/sched.c:666)
主要函数
srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{//根据请求参数,开启flv功能srs_assert(entry);bool drop_if_not_match = _srs_config->get_vhost_http_remux_drop_if_not_match(req->vhost);bool has_audio = _srs_config->get_vhost_http_remux_has_audio(req->vhost);bool has_video = _srs_config->get_vhost_http_remux_has_video(req->vhost);bool guess_has_av = _srs_config->get_vhost_http_remux_guess_has_av(req->vhost);if (srs_string_ends_with(entry->pattern, ".flv")) {w->header()->set_content_type("video/x-flv");enc_desc = "FLV";enc = new SrsFlvStreamEncoder();((SrsFlvStreamEncoder*)enc)->set_drop_if_not_match(drop_if_not_match);((SrsFlvStreamEncoder*)enc)->set_has_audio(has_audio);((SrsFlvStreamEncoder*)enc)->set_has_video(has_video);((SrsFlvStreamEncoder*)enc)->set_guess_has_av(guess_has_av);} else if (srs_string_ends_with(entry->pattern, ".aac")) {w->header()->set_content_type("audio/x-aac");enc_desc = "AAC";enc = new SrsAacStreamEncoder();//创建该 flv转换对应的consumerSrsAutoFree(SrsLiveConsumer, consumer);if ((err = source->create_consumer(hc, consumer)) != srs_success) {return srs_error_wrap(err, "create consumer");}if ((err = source->consumer_dumps(consumer, true, true, !enc->has_cache())) != srs_success) {return srs_error_wrap(err, "dumps consumer");}// the memory writer.SrsBufferWriter writer(w);if ((err = enc->initialize(&writer, cache)) != srs_success) {return srs_error_wrap(err, "init encoder");}//把gop缓存发给新创建的consumer// if gop cache enabled for encoder, dump to consumer.if (enc->has_cache()) {if ((err = enc->dump_cache(consumer, source->jitter())) != srs_success) {return srs_error_wrap(err, "encoder dump cache");}}//开启一个while 循环,一直轮训读取rtmp数据,进行转换while (/*entry->enabled*/ true) {// Whether client closed the FD.if ((err = trd->pull()) != srs_success) {return srs_error_wrap(err, "recv thread");}// get messages from consumer.// each msg in msgs.msgs must be free, for the SrsMessageArray never free them.int count = 0;if ((err = consumer->dump_packets(&msgs, count)) != srs_success) {return srs_error_wrap(err, "consumer dump packets");}//写入flv 对应的tag// sendout all messages.if (ffe) {err = ffe->write_tags(msgs.msgs, count);}
SrsFlvStreamEncoder
最终会调用到:SrsFlvStreamEncoder
srs_error_t SrsFlvStreamEncoder::write_tags(SrsSharedPtrMessage** msgs, int count)
{// For https://github.com/ossrs/srs/issues/939//首先写入 flv headerif (!header_written) {bool has_video = has_video_; bool has_audio = has_audio_;if ((err = write_header(has_video, has_audio)) != srs_success) {return srs_error_wrap(err, "write header");}//再写入对应的 tag// Write tags after header is done.return enc->write_tags(msgs, count);
}
SrsFlvTransmuxer
写tag,协议层面见类SrsFlvTransmuxer
srs_error_t SrsFlvTransmuxer::write_tags(SrsSharedPtrMessage** msgs, int count)
{srs_error_t err = srs_success;// Do realloc the iovss if required.iovec* iovss = iovss_cache;do {int nn_might_iovss = 3 * count;if (nb_iovss_cache < nn_might_iovss) {srs_freepa(iovss_cache);nb_iovss_cache = nn_might_iovss;iovss = iovss_cache = new iovec[nn_might_iovss];}} while (false);// Do realloc the tag headers if required.char* cache = tag_headers;if (nb_tag_headers < count) {srs_freepa(tag_headers);nb_tag_headers = count;cache = tag_headers = new char[SRS_FLV_TAG_HEADER_SIZE * count];}// Do realloc the pts if required.char* pts = ppts;if (nb_ppts < count) {srs_freepa(ppts);nb_ppts = count;pts = ppts = new char[SRS_FLV_PREVIOUS_TAG_SIZE * count];}// Now all caches are ok, start to write all messages.iovec* iovs = iovss; int nn_real_iovss = 0;for (int i = 0; i < count; i++) {SrsSharedPtrMessage* msg = msgs[i];// Cache FLV packet header.if (msg->is_audio()) {if (drop_if_not_match_ && !has_audio_) continue; // Ignore audio packets if no audio stream.cache_audio(msg->timestamp, msg->payload, msg->size, cache);} else if (msg->is_video()) {if (drop_if_not_match_ && !has_video_) continue; // Ignore video packets if no video stream.cache_video(msg->timestamp, msg->payload, msg->size, cache);} else {cache_metadata(SrsFrameTypeScript, msg->payload, msg->size, cache);}// Cache FLV pts.cache_pts(SRS_FLV_TAG_HEADER_SIZE + msg->size, pts);// Set cache to iovec.iovs[0].iov_base = cache;iovs[0].iov_len = SRS_FLV_TAG_HEADER_SIZE;iovs[1].iov_base = msg->payload;iovs[1].iov_len = msg->size;iovs[2].iov_base = pts;iovs[2].iov_len = SRS_FLV_PREVIOUS_TAG_SIZE;// Move to next cache.cache += SRS_FLV_TAG_HEADER_SIZE;pts += SRS_FLV_PREVIOUS_TAG_SIZE;iovs += 3; nn_real_iovss += 3;}// Send out all data carried by iovec.if ((err = writer->writev(iovss, nn_real_iovss, NULL)) != srs_success) {return srs_error_wrap(err, "write flv tags failed");}return err;
}
这篇关于srs rtmp转flv的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!