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转换对应的consumer
SrsAutoFree(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 header
if (!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;
}
原文地址:https://blog.csdn.net/lcalqf/article/details/136043572
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!