SDP信息格式分析
原因:由于webRtc媒體信息交互需要使用SDP數(shù)據(jù)格式,而且使用ffplay播放rtp數(shù)據(jù)流時需要首先獲取SDP文件信息,故通過對比SDP信息進行分析.
概述:SDP(?Session Description Protocol)與其說是一個協(xié)議不如確切的說是一種文本封裝格式,關(guān)于SDP的傳輸需要使用到其他協(xié)議傳輸,比如Http,RTSP等,SDP文本中主要包含會話信息和媒體信息,按照規(guī)定的格式進行填寫和擴展。https://www.rfc-editor.org/rfc/rfc2327.txt
首先使用ffmpeg進行rtp推流以及ffplay進行rtp播放命令行如下:通過命令行可以看出ffplay播放rtp需要首先使用sdp文件進行獲取媒體信息。
ffmpeg -re -i gop.264 -vcodec copy -f rtp rtp://127.0.0.1:1234 > test_rtp_h264.sdpffplay -protocol_whitelist "file,udp,rtp" -i test_rtp_h264.sdpffplay -protocol_whitelist "file,udp,rtp" -i rtp://127.0.0.1:1234 (失敗)rtp推流生成的sdp文件信息如下:可以看出包括會話信息和媒體信息。接下來具體分析SDP數(shù)據(jù)個關(guān)鍵字含義
SDP: v=0o=- 0 0 IN IP4 127.0.0.1s=No Namec=IN IP4 127.0.0.1t=0 0a=tool:libavformat 57.72.101m=video 1234 RTP/AVP 96a=rtpmap:96 H264/90000a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAKKzZQHgCJ+XARAAAD6QAAu4APGDGWA==,aOvjyyLA; profile-level-id=640028v? = :協(xié)議版本,目前為0.
o? = :<會話名><會話標識><版本><網(wǎng)絡(luò)類型><地址類型>,主要表述會話源,IN:標識internet地址類型為文本類型.
s? =: <會話名>,每個會話描述必須只有一個會話名
c? = :<網(wǎng)絡(luò)類型><地址類型><連接地址>,主要用于包含連接數(shù)據(jù).
t? ?= :<開始時間><結(jié)束時間>,會話的實效性,如果結(jié)束為0則表示該會話不受限制,如果開始也為0則表示視為永久性。
m = :<媒體><端口><傳輸層><格式列表>,媒體信息描述,每個媒體描述都是通過m字段開頭。媒體類型包括:video,audio,application,data,control,傳輸層:對應(yīng)的傳輸協(xié)議,格式列表:對應(yīng)的負債類型。
a? =<屬性>:<值>,用于SDP擴展,可以分為會話級屬性和媒體級屬性.
a = rtpmap:<負載類型><編碼類型><時鐘頻率><編碼參數(shù)>,對于音頻流,編碼參數(shù)為聲道數(shù)量,視頻無該參數(shù).
a = tool:<工具名><版本號>。
接下來為webRtc交互的SDP數(shù)據(jù)如下:
{ "sdp" : "v=0\r\no=- 449280690799912824 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS stream_label\r\nm=audio 9 UDP/TLS/RTP/SAVPF 103 104 0 8 106 105 13 112 113 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:cF8F\r\na=ice-pwd:/mLl0OIRuzAUE0gXyCJ+Z+P4\r\na=fingerprint:sha-25679:B2:E3:E0:8A:0C:CB:DA:D2:12:D6:50:FB:FD:B5:E8:18:CA:C6:F6:07:26:0E:F7:CF:53:7F:80:E4:76:73:3B\r\na=setup:actpass\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:112 telephone-event/32000\r\na=rtpmap:113 telephone-event/16000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:2929087609 cname:O025nGVLc6C+RI1k\r\na=ssrc:2929087609 msid:stream_label audio_label\r\na=ssrc:2929087609 mslabel:stream_label\r\na=ssrc:2929087609 label:audio_label\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 98 100 102 127 97 99 101 125\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:cF8F\r\na=ice-pwd:/mLl0OIRuzAUE0gXyCJ+Z+P4\r\na=fingerprint:sha-256 79:B2:E3:E0:8A:0C:CB:DA:D2:12:D6:50:FB:FD:B5:E8:18:CA:C6:F6:07:26:0E:F7:CF:53:7F:80:E4:76:73:3B\r\na=setup:actpass\r\na=mid:video\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:4 urn:3gpp:video-orientation\r\na=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=sendrecv\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 VP8/90000\r\na=rtcp-fb:96 ccm fir\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=rtcp-fb:96 goog-remb\r\na=rtcp-fb:96 transport-cc\r\na=rtpmap:98 VP9/90000\r\na=rtcp-fb:98 ccm fir\r\na=rtcp-fb:98 nack\r\na=rtcp-fb:98 nack pli\r\na=rtcp-fb:98 goog-remb\r\na=rtcp-fb:98 transport-cc\r\na=rtpmap:100 H264/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 nack pli\r\na=rtcp-fb:100 goog-remb\r\na=rtcp-fb:100 transport-cc\r\na=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\r\na=rtpmap:102 red/90000\r\na=rtpmap:127 ulpfec/90000\r\na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\na=rtpmap:99 rtx/90000\r\na=fmtp:99 apt=98\r\na=rtpmap:101 rtx/90000\r\na=fmtp:101 apt=100\r\na=rtpmap:125 rtx/90000\r\na=fmtp:125 apt=102\r\na=ssrc-group:FID 4198811712 3825804760\r\na=ssrc:4198811712 cname:O025nGVLc6C+RI1k\r\na=ssrc:4198811712 msid:stream_label video_label\r\na=ssrc:4198811712 mslabel:stream_label\r\na=ssrc:4198811712 label:video_label\r\na=ssrc:3825804760 cname:O025nGVLc6C+RI1k\r\na=ssrc:3825804760 msid:stream_label video_label\r\na=ssrc:3825804760 mslabel:stream_label\r\na=ssrc:3825804760 label:video_label\r\n","type" : "offer" }SDP主要用于進行媒體交互,通過m字段包含媒體類型,通過a字段進行媒體類型的細化說明。利用FFmpeg進行SDP數(shù)據(jù)解析代碼如下:可以看出主要使用到AVIOContext,而具體的SDP解析并沒有深入分析。
int main(int argc, char *argv[]) {//av_register_all();av_log_set_level(AV_LOG_DEBUG);FILE *pSDP = nullptr;errno_t er = fopen_s(&pSDP, "h264.sdp", "rb+");if (er != 0){printf("fopen_s failed.\n");goto end;}fseek(pSDP, 0, SEEK_END);int iSize = ftell(pSDP);fseek(pSDP, 0, SEEK_SET);unsigned char* pBuffer = (unsigned char *)av_malloc(iSize);int iLen = fread(pBuffer, 1, iSize, pSDP);if (iLen != iSize){printf("iSize=%d,iLen=%d",iSize,iLen);goto end;}AVIOContext *pIoCtx = nullptr;pIoCtx = avio_alloc_context(pBuffer, iSize, 0, NULL, NULL, NULL, NULL);AVFormatContext *pForCtx = nullptr;pForCtx = avformat_alloc_context();pForCtx->pb = pIoCtx;pForCtx->iformat = av_find_input_format("sdp");int ir = avformat_open_input(&pForCtx, NULL, nullptr , nullptr);if (ir != 0){printf("avformat_open_input Failed\n");goto end;}ir = avformat_find_stream_info(pForCtx, nullptr);if (ir < 0){printf("avformat_find_stream_info Failed.\n");goto end;}int iIndex = -1;for (int i = 0; i < pForCtx->nb_streams; i++){if (pForCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){iIndex = i;break;}}if (iIndex < 0){printf("get video stream failed\n");goto end;}AVCodec *pCodec = nullptr;AVCodecContext *pCodCtx = nullptr;pCodec = avcodec_find_decoder(pForCtx->streams[iIndex]->codecpar->codec_id);pCodCtx = avcodec_alloc_context3(pCodec);ir = avcodec_parameters_to_context(pCodCtx, pForCtx->streams[iIndex]->codecpar);if (ir < 0){printf("avcodec_parameters_to_context failed\n");goto end;}ir = avcodec_open2(pCodCtx, pCodec,nullptr);if (ir != 0){printf("avcodec_open2 failed\n");goto end;}AVPacket pk;while (av_read_frame(pForCtx, &pk) == 0){if (pk.stream_index == iIndex){printf("Recv pts=%lld,dts=%lld,size=%d\n",pk.pts,pk.dts,pk.size);}av_packet_unref(&pk);} end:fclose(pSDP);av_free(pBuffer);avformat_free_context(pForCtx);for (;;);return 0; }總結(jié):以上為sdp的簡單分析,通過分析可知sdp只是用來進行媒體交互的一種文本格式,且在媒體交互中該文本格式主要包含了媒體信息,而通過m字段可以表明傳輸?shù)拿襟w類型,通過a字段對媒體類型進行詳細描述。主要包括:音視頻對應(yīng)的負載類型,編碼類型,傳輸協(xié)議,時鐘頻率等。
總結(jié)
- 上一篇: Python 某宝的登陆,过滑块
- 下一篇: Linux(RedHat9.0)下Als