mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	for #316, add codec info to stream.
This commit is contained in:
		
							parent
							
								
									8bf60895a9
								
							
						
					
					
						commit
						04f3f2a8f8
					
				
					 8 changed files with 286 additions and 50 deletions
				
			
		| 
						 | 
				
			
			@ -217,6 +217,7 @@ that is:
 | 
			
		|||
#define __SRS_JFIELD_STR(k, v) "\"" << k << "\":\"" << v << "\""
 | 
			
		||||
#define __SRS_JFIELD_ORG(k, v) "\"" << k << "\":" << std::dec << v
 | 
			
		||||
#define __SRS_JFIELD_BOOL(k, v) __SRS_JFIELD_ORG(k, (v? "true":"false"))
 | 
			
		||||
#define __SRS_JFIELD_NULL(k) "\"" << k << "\":null"
 | 
			
		||||
#define __SRS_JFIELD_ERROR(ret) "\"" << "code" << "\":" << ret
 | 
			
		||||
#define __SRS_JFIELD_CONT ","
 | 
			
		||||
#define __SRS_JOBJECT_END "}"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -202,7 +202,7 @@ int SrsRtmpConn::do_cycle()
 | 
			
		|||
    ret = service_cycle();
 | 
			
		||||
    http_hooks_on_close();
 | 
			
		||||
    SrsStatistic* stat = SrsStatistic::instance();
 | 
			
		||||
    stat->on_close(_srs_context->get_id());
 | 
			
		||||
    stat->on_disconnect(_srs_context->get_id());
 | 
			
		||||
    
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,7 @@ using namespace std;
 | 
			
		|||
#include <srs_kernel_utility.hpp>
 | 
			
		||||
#include <srs_kernel_codec.hpp>
 | 
			
		||||
#include <srs_rtmp_msg_array.hpp>
 | 
			
		||||
#include <srs_app_statistic.hpp>
 | 
			
		||||
 | 
			
		||||
#define CONST_MAX_JITTER_MS         500
 | 
			
		||||
#define DEFAULT_FRAME_TIME_MS         40
 | 
			
		||||
| 
						 | 
				
			
			@ -1373,6 +1374,7 @@ int SrsSource::on_audio(SrsCommonMessage* __audio)
 | 
			
		|||
 | 
			
		||||
    // cache the sequence header of aac, or first packet of mp3.
 | 
			
		||||
    // for example, the mp3 is used for hls to write the "right" audio codec.
 | 
			
		||||
    // TODO: FIXME: to refine the stream info system.
 | 
			
		||||
    bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg.payload, msg.size);
 | 
			
		||||
    if (is_aac_sequence_header || !cache_sh_audio) {
 | 
			
		||||
        srs_freep(cache_sh_audio);
 | 
			
		||||
| 
						 | 
				
			
			@ -1392,6 +1394,13 @@ int SrsSource::on_audio(SrsCommonMessage* __audio)
 | 
			
		|||
        
 | 
			
		||||
        static int flv_sample_sizes[] = {8, 16, 0};
 | 
			
		||||
        static int flv_sound_types[] = {1, 2, 0};
 | 
			
		||||
        
 | 
			
		||||
        // when got audio stream info.
 | 
			
		||||
        SrsStatistic* stat = SrsStatistic::instance();
 | 
			
		||||
        if ((ret = stat->on_audio_info(_req, SrsCodecAudioAAC, sample.sound_rate, sample.sound_type, codec.aac_profile)) != ERROR_SUCCESS) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        srs_trace("%dB audio sh, "
 | 
			
		||||
            "codec(%d, profile=%d, %dchannels, %dkbps, %dHZ), "
 | 
			
		||||
            "flv(%dbits, %dchannels, %dHZ)", 
 | 
			
		||||
| 
						 | 
				
			
			@ -1515,6 +1524,12 @@ int SrsSource::on_video(SrsCommonMessage* __video)
 | 
			
		|||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // when got video stream info.
 | 
			
		||||
        SrsStatistic* stat = SrsStatistic::instance();
 | 
			
		||||
        if ((ret = stat->on_video_info(_req, SrsCodecVideoAVC, codec.avc_profile, codec.avc_level)) != ERROR_SUCCESS) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        srs_trace("%dB video sh, "
 | 
			
		||||
            "codec(%d, profile=%d, level=%d, %dx%d, %dkbps, %dfps, %ds)",
 | 
			
		||||
            msg.size, codec.video_codec_id,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,12 +50,29 @@ SrsStatisticStream::SrsStatisticStream()
 | 
			
		|||
{
 | 
			
		||||
    id = __srs_generate_id();
 | 
			
		||||
    vhost = NULL;
 | 
			
		||||
    
 | 
			
		||||
    has_video = false;
 | 
			
		||||
    vcodec = SrsCodecVideoReserved;
 | 
			
		||||
    avc_profile = 0;
 | 
			
		||||
    avc_level = 0;
 | 
			
		||||
    
 | 
			
		||||
    has_audio = false;
 | 
			
		||||
    acodec = SrsCodecAudioReserved1;
 | 
			
		||||
    asample_rate = SrsCodecAudioSampleRateReserved;
 | 
			
		||||
    asound_type = SrsCodecAudioSoundTypeReserved;
 | 
			
		||||
    aac_profile = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SrsStatisticStream::~SrsStatisticStream()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SrsStatisticStream::close()
 | 
			
		||||
{
 | 
			
		||||
    has_video = false;
 | 
			
		||||
    has_audio = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SrsStatistic* SrsStatistic::_instance = new SrsStatistic();
 | 
			
		||||
 | 
			
		||||
SrsStatistic::SrsStatistic()
 | 
			
		||||
| 
						 | 
				
			
			@ -93,34 +110,54 @@ SrsStatistic* SrsStatistic::instance()
 | 
			
		|||
    return _instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SrsStatistic::on_video_info(SrsRequest* req, 
 | 
			
		||||
    SrsCodecVideo vcodec, u_int8_t avc_profile, u_int8_t avc_level
 | 
			
		||||
) {
 | 
			
		||||
    int ret = ERROR_SUCCESS;
 | 
			
		||||
    
 | 
			
		||||
    SrsStatisticVhost* vhost = create_vhost(req);
 | 
			
		||||
    SrsStatisticStream* stream = create_stream(vhost, req);
 | 
			
		||||
 | 
			
		||||
    stream->has_video = true;
 | 
			
		||||
    stream->vcodec = vcodec;
 | 
			
		||||
    stream->avc_profile = avc_profile;
 | 
			
		||||
    stream->avc_level = avc_level;
 | 
			
		||||
    
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SrsStatistic::on_audio_info(SrsRequest* req,
 | 
			
		||||
    SrsCodecAudio acodec, SrsCodecAudioSampleRate asample_rate, SrsCodecAudioSoundType asound_type,
 | 
			
		||||
    u_int8_t aac_profile
 | 
			
		||||
) {
 | 
			
		||||
    int ret = ERROR_SUCCESS;
 | 
			
		||||
    
 | 
			
		||||
    SrsStatisticVhost* vhost = create_vhost(req);
 | 
			
		||||
    SrsStatisticStream* stream = create_stream(vhost, req);
 | 
			
		||||
 | 
			
		||||
    stream->has_audio = true;
 | 
			
		||||
    stream->acodec = acodec;
 | 
			
		||||
    stream->asample_rate = asample_rate;
 | 
			
		||||
    stream->asound_type = asound_type;
 | 
			
		||||
    stream->aac_profile = aac_profile;
 | 
			
		||||
    
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SrsStatistic::on_stream_close(SrsRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    SrsStatisticVhost* vhost = create_vhost(req);
 | 
			
		||||
    SrsStatisticStream* stream = create_stream(vhost, req);
 | 
			
		||||
 | 
			
		||||
    stream->close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SrsStatistic::on_client(int id, SrsRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    int ret = ERROR_SUCCESS;
 | 
			
		||||
    
 | 
			
		||||
    // create vhost if not exists.
 | 
			
		||||
    SrsStatisticVhost* vhost = NULL;
 | 
			
		||||
    if (vhosts.find(req->vhost) == vhosts.end()) {
 | 
			
		||||
        vhost = new SrsStatisticVhost();
 | 
			
		||||
        vhost->vhost = req->vhost;
 | 
			
		||||
        vhosts[req->vhost] = vhost;
 | 
			
		||||
    } else {
 | 
			
		||||
        vhost = vhosts[req->vhost];
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // the url to identify the stream.
 | 
			
		||||
    std::string url = req->get_stream_url();
 | 
			
		||||
    
 | 
			
		||||
    // create stream if not exists.
 | 
			
		||||
    SrsStatisticStream* stream = NULL;
 | 
			
		||||
    if (streams.find(url) == streams.end()) {
 | 
			
		||||
        stream = new SrsStatisticStream();
 | 
			
		||||
        stream->vhost = vhost;
 | 
			
		||||
        stream->stream = req->stream;
 | 
			
		||||
        stream->url = url;
 | 
			
		||||
        streams[url] = stream;
 | 
			
		||||
    } else {
 | 
			
		||||
        stream = streams[url];
 | 
			
		||||
    }
 | 
			
		||||
    SrsStatisticVhost* vhost = create_vhost(req);
 | 
			
		||||
    SrsStatisticStream* stream = create_stream(vhost, req);
 | 
			
		||||
 | 
			
		||||
    // create client if not exists
 | 
			
		||||
    SrsStatisticClient* client = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +172,7 @@ int SrsStatistic::on_client(int id, SrsRequest* req)
 | 
			
		|||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SrsStatistic::on_close(int id)
 | 
			
		||||
void SrsStatistic::on_disconnect(int id)
 | 
			
		||||
{
 | 
			
		||||
    std::map<int, SrsStatisticClient*>::iterator it;
 | 
			
		||||
    it = clients.find(id);
 | 
			
		||||
| 
						 | 
				
			
			@ -198,10 +235,74 @@ int SrsStatistic::dumps_streams(stringstream& ss)
 | 
			
		|||
                << __SRS_JFIELD_ORG("id", stream->id) << __SRS_JFIELD_CONT
 | 
			
		||||
                << __SRS_JFIELD_STR("name", stream->stream) << __SRS_JFIELD_CONT
 | 
			
		||||
                << __SRS_JFIELD_ORG("vhost", stream->vhost->id) << __SRS_JFIELD_CONT
 | 
			
		||||
                << __SRS_JFIELD_ORG("clients", client_num)
 | 
			
		||||
            << __SRS_JOBJECT_END;
 | 
			
		||||
                << __SRS_JFIELD_ORG("clients", client_num) << __SRS_JFIELD_CONT;
 | 
			
		||||
                
 | 
			
		||||
        if (!stream->has_video) {
 | 
			
		||||
            ss  << __SRS_JFIELD_NULL("video") << __SRS_JFIELD_CONT;
 | 
			
		||||
        } else {
 | 
			
		||||
            ss  << __SRS_JFIELD_NAME("video")
 | 
			
		||||
                    << __SRS_JOBJECT_START
 | 
			
		||||
                        << __SRS_JFIELD_STR("codec", srs_codec_video2str(stream->vcodec)) << __SRS_JFIELD_CONT
 | 
			
		||||
                        << __SRS_JFIELD_ORG("profile", (int)stream->avc_profile) << __SRS_JFIELD_CONT
 | 
			
		||||
                        << __SRS_JFIELD_ORG("level", (int)stream->avc_level)
 | 
			
		||||
                    << __SRS_JOBJECT_END
 | 
			
		||||
                << __SRS_JFIELD_CONT;
 | 
			
		||||
        }
 | 
			
		||||
                
 | 
			
		||||
        if (!stream->has_audio) {
 | 
			
		||||
            ss  << __SRS_JFIELD_NULL("audio");
 | 
			
		||||
        } else {
 | 
			
		||||
            ss  << __SRS_JFIELD_NAME("audio")
 | 
			
		||||
                    << __SRS_JOBJECT_START
 | 
			
		||||
                        << __SRS_JFIELD_STR("codec", srs_codec_audio2str(stream->acodec)) << __SRS_JFIELD_CONT
 | 
			
		||||
                        << __SRS_JFIELD_ORG("sample_rate", (int)flv_sample_rates[stream->asample_rate]) << __SRS_JFIELD_CONT
 | 
			
		||||
                        << __SRS_JFIELD_ORG("channel", (int)stream->asound_type + 1) << __SRS_JFIELD_CONT
 | 
			
		||||
                        << __SRS_JFIELD_STR("profile", srs_codec_aac_profile2str(stream->aac_profile))
 | 
			
		||||
                    << __SRS_JOBJECT_END;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        ss << __SRS_JOBJECT_END;
 | 
			
		||||
    }
 | 
			
		||||
    ss << __SRS_JARRAY_END;
 | 
			
		||||
    
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SrsStatisticVhost* SrsStatistic::create_vhost(SrsRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    SrsStatisticVhost* vhost = NULL;
 | 
			
		||||
    
 | 
			
		||||
    // create vhost if not exists.
 | 
			
		||||
    if (vhosts.find(req->vhost) == vhosts.end()) {
 | 
			
		||||
        vhost = new SrsStatisticVhost();
 | 
			
		||||
        vhost->vhost = req->vhost;
 | 
			
		||||
        vhosts[req->vhost] = vhost;
 | 
			
		||||
        return vhost;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vhost = vhosts[req->vhost];
 | 
			
		||||
    
 | 
			
		||||
    return vhost;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SrsStatisticStream* SrsStatistic::create_stream(SrsStatisticVhost* vhost, SrsRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    std::string url = req->get_stream_url();
 | 
			
		||||
    
 | 
			
		||||
    SrsStatisticStream* stream = NULL;
 | 
			
		||||
    
 | 
			
		||||
    // create stream if not exists.
 | 
			
		||||
    if (streams.find(url) == streams.end()) {
 | 
			
		||||
        stream = new SrsStatisticStream();
 | 
			
		||||
        stream->vhost = vhost;
 | 
			
		||||
        stream->stream = req->stream;
 | 
			
		||||
        stream->url = url;
 | 
			
		||||
        streams[url] = stream;
 | 
			
		||||
        return stream;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    stream = streams[url];
 | 
			
		||||
    
 | 
			
		||||
    return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		|||
#include <map>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include <srs_kernel_codec.hpp>
 | 
			
		||||
 | 
			
		||||
class SrsRequest;
 | 
			
		||||
 | 
			
		||||
struct SrsStatisticVhost
 | 
			
		||||
| 
						 | 
				
			
			@ -53,9 +55,33 @@ public:
 | 
			
		|||
    std::string app;
 | 
			
		||||
    std::string stream;
 | 
			
		||||
    std::string url;
 | 
			
		||||
public:
 | 
			
		||||
    bool has_video;
 | 
			
		||||
    SrsCodecVideo vcodec;
 | 
			
		||||
    // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
 | 
			
		||||
    u_int8_t avc_profile;
 | 
			
		||||
    // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
 | 
			
		||||
    u_int8_t avc_level;
 | 
			
		||||
public:
 | 
			
		||||
    bool has_audio;
 | 
			
		||||
    SrsCodecAudio acodec;
 | 
			
		||||
    SrsCodecAudioSampleRate asample_rate;
 | 
			
		||||
    SrsCodecAudioSoundType asound_type;
 | 
			
		||||
    /**
 | 
			
		||||
    * audio specified
 | 
			
		||||
    * audioObjectType, in 1.6.2.1 AudioSpecificConfig, page 33,
 | 
			
		||||
    * 1.5.1.1 Audio object type definition, page 23,
 | 
			
		||||
    *           in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf.
 | 
			
		||||
    */
 | 
			
		||||
    u_int8_t aac_profile;
 | 
			
		||||
public:
 | 
			
		||||
    SrsStatisticStream();
 | 
			
		||||
    virtual ~SrsStatisticStream();
 | 
			
		||||
public:
 | 
			
		||||
    /**
 | 
			
		||||
    * close the stream.
 | 
			
		||||
    */
 | 
			
		||||
    virtual void close();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SrsStatisticClient
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +99,7 @@ private:
 | 
			
		|||
    int64_t _server_id;
 | 
			
		||||
    // key: vhost name, value: vhost object.
 | 
			
		||||
    std::map<std::string, SrsStatisticVhost*> vhosts;
 | 
			
		||||
    // key: stream name, value: stream object.
 | 
			
		||||
    // key: stream url, value: stream object.
 | 
			
		||||
    std::map<std::string, SrsStatisticStream*> streams;
 | 
			
		||||
    // key: client id, value: stream object.
 | 
			
		||||
    std::map<int, SrsStatisticClient*> clients;
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +108,24 @@ private:
 | 
			
		|||
    virtual ~SrsStatistic();
 | 
			
		||||
public:
 | 
			
		||||
    static SrsStatistic* instance();
 | 
			
		||||
public:
 | 
			
		||||
    /**
 | 
			
		||||
    * when got video info for stream.
 | 
			
		||||
    */
 | 
			
		||||
    virtual int on_video_info(SrsRequest* req, 
 | 
			
		||||
        SrsCodecVideo vcodec, u_int8_t avc_profile, u_int8_t avc_level
 | 
			
		||||
    );
 | 
			
		||||
    /**
 | 
			
		||||
    * when got audio info for stream.
 | 
			
		||||
    */
 | 
			
		||||
    virtual int on_audio_info(SrsRequest* req,
 | 
			
		||||
        SrsCodecAudio acodec, SrsCodecAudioSampleRate asample_rate, SrsCodecAudioSoundType asound_type,
 | 
			
		||||
        u_int8_t aac_profile
 | 
			
		||||
    );
 | 
			
		||||
    /**
 | 
			
		||||
    * when close stream.
 | 
			
		||||
    */
 | 
			
		||||
    virtual void on_stream_close(SrsRequest* req);
 | 
			
		||||
public:
 | 
			
		||||
    /**
 | 
			
		||||
    * when got a client to publish/play stream,
 | 
			
		||||
| 
						 | 
				
			
			@ -90,9 +134,9 @@ public:
 | 
			
		|||
    */
 | 
			
		||||
    virtual int on_client(int id, SrsRequest* req);
 | 
			
		||||
    /**
 | 
			
		||||
    * client close
 | 
			
		||||
    * client disconnect
 | 
			
		||||
    */
 | 
			
		||||
    virtual void on_close(int id);
 | 
			
		||||
    virtual void on_disconnect(int id);
 | 
			
		||||
public:
 | 
			
		||||
    /**
 | 
			
		||||
    * get the server id, used to identify the server.
 | 
			
		||||
| 
						 | 
				
			
			@ -107,6 +151,9 @@ public:
 | 
			
		|||
    * dumps the streams to sstream in json.
 | 
			
		||||
    */
 | 
			
		||||
    virtual int dumps_streams(std::stringstream& ss);
 | 
			
		||||
private:
 | 
			
		||||
    virtual SrsStatisticVhost* create_vhost(SrsRequest* req);
 | 
			
		||||
    virtual SrsStatisticStream* create_stream(SrsStatisticVhost* vhost, SrsRequest* req);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue