WebRTC中RTP/RTCP協(xié)議實(shí)現(xiàn)分析

一 前言

</br>
RTP/RTCP協(xié)議是流媒體通信的基石碱璃。RTP協(xié)議定義流媒體數(shù)據(jù)在互聯(lián)網(wǎng)上傳輸?shù)臄?shù)據(jù)包格式,而RTCP協(xié)議則負(fù)責(zé)可靠傳輸脚曾、流量控制和擁塞控制等服務(wù)質(zhì)量保證闽瓢。在WebRTC項(xiàng)目中,RTP/RTCP模塊作為傳輸模塊的一部分蕊玷,負(fù)責(zé)對(duì)發(fā)送端采集到的媒體數(shù)據(jù)進(jìn)行進(jìn)行封包邮利,然后交給上層網(wǎng)絡(luò)模塊發(fā)送;在接收端RTP/RTCP模塊收到上層模塊的數(shù)據(jù)包后垃帅,進(jìn)行解包操作延届,最后把負(fù)載發(fā)送到解碼模塊。因此挺智,RTP/RTCP 模塊在WebRTC通信中發(fā)揮非常重要的作用祷愉。</br>

本文在深入研究WebRTC源代碼的基礎(chǔ)上窗宦,以Video數(shù)據(jù)的發(fā)送和接收為例赦颇,力求用簡(jiǎn)潔語(yǔ)言描述RTP/RTCP模塊的實(shí)現(xiàn)細(xì)節(jié)二鳄,為進(jìn)一步深入掌握WebRTC打下良好基礎(chǔ)。</br>

二 RTP/RTCP協(xié)議概述

</br>
RTP協(xié)議是Internet上針對(duì)流媒體傳輸?shù)幕A(chǔ)協(xié)議媒怯,該協(xié)議詳細(xì)說(shuō)明在互聯(lián)網(wǎng)上傳輸音視頻的標(biāo)準(zhǔn)數(shù)據(jù)包格式订讼。RTP協(xié)議本身只保證實(shí)時(shí)數(shù)據(jù)的傳輸,RTCP協(xié)議則負(fù)責(zé)流媒體的傳輸質(zhì)量保證扇苞,提供流量控制和擁塞控制等服務(wù)欺殿。在RTP會(huì)話期間,各參與者周期性彼此發(fā)送RTCP報(bào)文鳖敷。報(bào)文中包含各參與者數(shù)據(jù)發(fā)送和接收等統(tǒng)計(jì)信息脖苏,參與者可以據(jù)此動(dòng)態(tài)控制流媒體傳輸質(zhì)量。</br>

RFC3550 [1]定義RTP/RTCP協(xié)議的基本內(nèi)容定踱,包括報(bào)文格式棍潘、傳輸規(guī)則等。除此之外崖媚,IETF還定義一系列擴(kuò)展協(xié)議亦歉,包括RTP協(xié)議基于檔次的擴(kuò)展,和RTCP協(xié)議基于報(bào)文類型的擴(kuò)展畅哑,等等肴楷。詳細(xì)內(nèi)容可參考文獻(xiàn)[2]。</br>

三 WebRTC線程關(guān)系和數(shù)據(jù)流

</br>
WebRTC對(duì)外提供兩個(gè)線程:Signal和Worker荠呐,前者負(fù)責(zé)信令數(shù)據(jù)的處理和傳輸赛蔫,后者負(fù)責(zé)媒體數(shù)據(jù)的處理和傳輸。在WebRTC內(nèi)部泥张,有一系列線程各司其職呵恢,相互協(xié)作完成數(shù)據(jù)流管線。下面以Video數(shù)據(jù)的處理流程為例圾结,說(shuō)明WebRTC內(nèi)部的線程合作關(guān)系瑰剃。</br>

圖1 WebRTC線程關(guān)系和數(shù)據(jù)管線

如圖1所示,Capture線程從攝像頭采集原始數(shù)據(jù)筝野,得到VideoFrame晌姚;Capture線程是系統(tǒng)相關(guān)的,在Linux系統(tǒng)上可能是調(diào)用V4L2接口的線程歇竟,而在Mac系統(tǒng)上可能是調(diào)用AVFoundation框架的接口挥唠。接下來(lái)原始數(shù)據(jù)VideoFrame從Capture線程到達(dá)Worker線程,Worker線程起搬運(yùn)工的作用焕议,沒(méi)有對(duì)數(shù)據(jù)做特別處理宝磨,而是轉(zhuǎn)發(fā)到Encoder線程。Encoder線程調(diào)用具體的編碼器(如VP8, H264)對(duì)原始數(shù)據(jù)VideoFrame進(jìn)行編碼,編碼后的輸出進(jìn)一步進(jìn)行RTP封包形成RTP數(shù)據(jù)包唤锉。然后RTP數(shù)據(jù)包發(fā)送到Pacer線程進(jìn)行平滑發(fā)送世囊,Pacer線程會(huì)把RTP數(shù)據(jù)包推送到Network線程。最終Network線程調(diào)用傳輸層系統(tǒng)函數(shù)把數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)窿祥。</br>

在接收端株憾,Network線程從網(wǎng)絡(luò)接收字節(jié)流,接著Worker線程反序列化為RTP數(shù)據(jù)包晒衩,并在VCM模塊進(jìn)行組幀操作嗤瞎。Decoder線程對(duì)組幀完成的數(shù)據(jù)幀進(jìn)行解碼操作,解碼后的原始數(shù)據(jù)VideoFrame會(huì)推送到IncomingVideoStream線程听系,該線程把VideoStream投放到render進(jìn)行渲染顯示贝奇。至此,一幀視頻數(shù)據(jù)完成從采集到顯示的完整過(guò)程靠胜。</br>

在上述過(guò)程中掉瞳,RTP數(shù)據(jù)包產(chǎn)生在發(fā)送端編碼完成后,其編碼輸出被封裝為RTP報(bào)文髓帽,然后經(jīng)序列化發(fā)送到網(wǎng)絡(luò)菠赚。在接收端由網(wǎng)絡(luò)線程收到網(wǎng)絡(luò)數(shù)據(jù)包后,經(jīng)過(guò)反序列化還原成RTP報(bào)文郑藏,然后經(jīng)過(guò)解包得到媒體數(shù)據(jù)負(fù)載衡查,供解碼器進(jìn)行解碼。RTP報(bào)文在發(fā)送和接收過(guò)程中必盖,會(huì)執(zhí)行一系列統(tǒng)計(jì)操作拌牲,統(tǒng)計(jì)結(jié)果作為數(shù)據(jù)源供構(gòu)造RTCP報(bào)文之用。RTP報(bào)文構(gòu)造歌粥、發(fā)送/接收統(tǒng)計(jì)和RTCP報(bào)文構(gòu)造塌忽、解析反饋,是接下來(lái)分析的重點(diǎn)失驶。</br>

四 RTP報(bào)文發(fā)送和接收

</br>
RTP報(bào)文的構(gòu)造和發(fā)送發(fā)生在編碼器編碼之后土居、網(wǎng)絡(luò)層發(fā)送數(shù)據(jù)包之前,而接收和解包發(fā)生在網(wǎng)絡(luò)層接收數(shù)據(jù)之后嬉探、解碼器編碼之前擦耀。本節(jié)詳細(xì)分析這兩部分的內(nèi)容。</br>

4.1 RTP報(bào)文構(gòu)造和發(fā)送

</br>
圖2描述發(fā)送端編碼之后RTP報(bào)文的構(gòu)造和發(fā)送過(guò)程涩堤,涉及三個(gè)線程:Encoder眷蜓、Pacer和Network,分別負(fù)責(zé)編碼和構(gòu)造RTP報(bào)文胎围,平滑發(fā)送和傳輸層發(fā)送吁系。下面詳細(xì)描述這三個(gè)線程的協(xié)同工作過(guò)程德召。</br>

圖2 RTP報(bào)文構(gòu)造和發(fā)送

Encode線程調(diào)用編碼器(比如VP8)對(duì)采集到的Raw VideoFrame進(jìn)行編碼,編碼完成以后汽纤,其輸出EncodedImage通過(guò)回調(diào)到達(dá)VideoSendStream::Encoded()函數(shù)上岗,進(jìn)而通過(guò)PayloadRouter路由到ModuleRtpRtcpImpl::SendOutgoingData()。接下來(lái)冒版,該函數(shù)向下調(diào)用RtpSender::SendOutgoingData()液茎,進(jìn)而調(diào)用RtpSenderVideo::SendVideo()逞姿。該函數(shù)對(duì)EncodedImage進(jìn)行打包辞嗡,然后填充RTP頭部構(gòu)造RTP報(bào)文;如果配置了FEC滞造,則進(jìn)一步封裝為FEC報(bào)文续室。最后返回RtpSender::SendToNetwork()進(jìn)行下一步發(fā)送。</br>

RtpSender::SendToNetwork()函數(shù)把報(bào)文存儲(chǔ)到RTPPacketHistory結(jié)構(gòu)中進(jìn)行緩存谒养。接下來(lái)如果開(kāi)啟PacedSending挺狰,則構(gòu)造Packe發(fā)送到PacedSender進(jìn)行排隊(duì),否則直接發(fā)送到網(wǎng)絡(luò)層买窟。</br>

Pacer線程周期性從隊(duì)列中獲取Packet丰泊,然后調(diào)用PacedSender::SendPacket()進(jìn)行發(fā)送,接下來(lái)經(jīng)過(guò)ModuleRtpRtcpImpl到達(dá)RtpSender::TimeToSendPacket()始绍。該函數(shù)首先從RtpPacketHistory緩存中拿到Packet的負(fù)載瞳购,然后調(diào)用PrepareAndSendPacket()函數(shù):更新RtpHeader的相關(guān)域,統(tǒng)計(jì)延遲和數(shù)據(jù)包亏推,調(diào)用SendPacketToNetwork()把報(bào)文發(fā)送到傳輸模塊学赛。</br>

Network線程則調(diào)用傳輸層套接字執(zhí)行數(shù)據(jù)發(fā)送操作。至此吞杭,發(fā)送端的RTP構(gòu)造和發(fā)送流程完成盏浇。需要注意的是,在RtpSender中進(jìn)行Rtp發(fā)送后芽狗,會(huì)統(tǒng)計(jì)RTP報(bào)文相關(guān)信息绢掰。這些信息作為RTCP構(gòu)造SR/RR報(bào)文的數(shù)據(jù)來(lái)源,因此非常重要童擎。</br>

4.2 RTP報(bào)文接收和解析

</br>
在接收端滴劲,RTP報(bào)文的接收和解包操作主要在Worker線程中執(zhí)行,RTP報(bào)文從Network線程拿到后柔昼,進(jìn)入Worker線程哑芹,經(jīng)過(guò)解包操作,進(jìn)入VCM模塊捕透,由Decode線程進(jìn)行解碼聪姿,最終由Render線程進(jìn)行渲染碴萧。下圖3描述RTP報(bào)文在Worker線程中的處理流程。</br>

圖3 RTP報(bào)文接收和解析

RTP數(shù)據(jù)包經(jīng)網(wǎng)絡(luò)層到達(dá)Call對(duì)象末购,根據(jù)其SSRC找到對(duì)應(yīng)的VideoReceiveStream破喻,通過(guò)調(diào)用其DeliverRtp()函數(shù)到RtpStreamReceiver::DeliverRtp()。該函數(shù)首先解析數(shù)據(jù)包得到RTP頭部信息盟榴,接下來(lái)執(zhí)行三個(gè)操作:1.碼率估計(jì)曹质;2.繼續(xù)發(fā)送數(shù)據(jù)包;3.接收統(tǒng)計(jì)擎场。碼率估計(jì)模塊使用GCC算法估計(jì)碼率羽德,構(gòu)造REMB報(bào)文,交給RtpRtcp模塊發(fā)送回發(fā)送端迅办。而接收統(tǒng)計(jì)則統(tǒng)計(jì)RTP接收信息宅静,這些信息作為RTCP RR報(bào)文的數(shù)據(jù)來(lái)源。下面重點(diǎn)分析接下來(lái)的數(shù)據(jù)包發(fā)送流程站欺。</br>

RtpStreamReceiver::ReceivePacket()首先判斷數(shù)據(jù)包是否是FEC報(bào)文姨夹,如果是則調(diào)用FecReceiver進(jìn)行解包,否則直接調(diào)用RtpReceiver::IncomingRtpPacket()矾策。該函數(shù)分析RTP報(bào)文得到通用的RTP頭部描述結(jié)構(gòu)磷账,然后調(diào)用RtpReceiverVideo::ParseRtpPacket()進(jìn)一步得到Video相關(guān)信息和負(fù)載,接著經(jīng)過(guò)回調(diào)返回RtpStreamReceiver對(duì)象贾虽。該對(duì)象把Rtp描述信息和負(fù)載發(fā)送到VCM模塊逃糟,繼續(xù)接下來(lái)的JitterBuffer緩存和解碼渲染操作。</br>

RTP報(bào)文解包過(guò)程是封包的逆過(guò)程榄鉴,重要的輸出信息是RTP頭部描述和媒體負(fù)載履磨,這些信息是下一步JitterBuffer緩存和解碼的基礎(chǔ)。另外對(duì)RTP報(bào)文進(jìn)行統(tǒng)計(jì)得到的信息則是RTCP RR報(bào)文的數(shù)據(jù)來(lái)源庆尘。</br>

五 RTCP報(bào)文發(fā)送和接收

</br>
RTCP協(xié)議是RTP協(xié)議的控制下可以剃诅,負(fù)責(zé)流媒體的服務(wù)質(zhì)量保證。比較常用的RTCP報(bào)文由發(fā)送端報(bào)告SR和接收端報(bào)告RR驶忌,分別包含數(shù)據(jù)發(fā)送統(tǒng)計(jì)信息和數(shù)據(jù)接收信息矛辕。這些信息對(duì)于流媒體質(zhì)量保證非常重要,比如碼率控制付魔、負(fù)載反饋聊品,等等。其他RTCP報(bào)文還有諸如SDES几苍、BYE翻屈、SDES等,RFC3550對(duì)此有詳細(xì)定義妻坝。</br>

本節(jié)重點(diǎn)分析WebRTC內(nèi)部RTCP報(bào)文的構(gòu)造伸眶、發(fā)送惊窖、接收、解析厘贼、反饋等流程界酒。需要再次強(qiáng)調(diào)的是,RTCP報(bào)文的數(shù)據(jù)源來(lái)自RTP報(bào)文發(fā)送和接收時(shí)的統(tǒng)計(jì)信息嘴秸。在WebRTC內(nèi)部毁欣,RTCP報(bào)文的發(fā)送采取周期性發(fā)送和及時(shí)發(fā)送相結(jié)合的策略:ModuleProcess線程周期性發(fā)送RTCP報(bào)文;而RtpSender則在每次發(fā)送RTP報(bào)文之前都判斷是否需要發(fā)送RTCP報(bào)文岳掐;另外在接收端碼率估計(jì)模塊構(gòu)造出REMB報(bào)文后凭疮,通過(guò)設(shè)置超時(shí)讓ModuleProcess模塊立即發(fā)送RTCP報(bào)文。</br>

5.1 RTCP報(bào)文構(gòu)造和發(fā)送

</br>
在發(fā)送端岩四,RTCP以周期性發(fā)送為基準(zhǔn)哭尝,輔以RTP報(bào)文發(fā)送時(shí)的及時(shí)發(fā)送和REMB報(bào)文的立即發(fā)送。發(fā)送過(guò)程主要包括Feedback信息獲取剖煌、RTCP報(bào)文構(gòu)造、序列化和發(fā)送逝淹。圖4描述了RTCP報(bào)文的構(gòu)造和發(fā)送過(guò)程耕姊。</br>

圖4 RTCP報(bào)文構(gòu)造和發(fā)送

ModuleProcess線程周期性調(diào)用ModuleRtpRtcpImpl::Process()函數(shù),該函數(shù)通過(guò)RTCPSender::TimeToSendRtcpReport()函數(shù)確定當(dāng)前是否需要立即發(fā)送RTCP報(bào)文栅葡。若是茉兰,則首先從RTPSender::GetDataCounters()獲取RTP發(fā)送統(tǒng)計(jì)信息,然后調(diào)用RTCPSender::SendRTCP()欣簇,接著是SendCompoundRTCP()發(fā)送RTCP組合報(bào)文规脸。關(guān)于RTCP組合報(bào)文的定義,請(qǐng)參考文獻(xiàn)[1]熊咽。</br>

在SendCompoundRTCP()函數(shù)中莫鸭,首先通過(guò)PrepareReport()確定將要發(fā)送何種類型的RTCP報(bào)文。然后針對(duì)每一種報(bào)文横殴,調(diào)用其構(gòu)造函數(shù)(如構(gòu)造SR報(bào)文為BuildSR()函數(shù))被因,構(gòu)造好的報(bào)文存儲(chǔ)在PacketContainer容器中。最后調(diào)用SendPackets()進(jìn)行發(fā)送衫仑。</br>

接下來(lái)每種RTCP報(bào)文都會(huì)調(diào)用各自的序列化函數(shù)梨与,把報(bào)文序列化為網(wǎng)絡(luò)字節(jié)流。最后通過(guò)回調(diào)到達(dá)PacketContainer::OnPacketReady()文狱,最終把字節(jié)流發(fā)送到傳輸層模塊:即通過(guò)TransportAdapter到達(dá)BaseChannel粥鞋,Network線程調(diào)用傳輸層套接字API發(fā)送數(shù)據(jù)到網(wǎng)絡(luò)。</br>

RTCP報(bào)文的構(gòu)造和發(fā)送過(guò)程總體不是很復(fù)雜瞄崇,最核心的操作就是獲取數(shù)據(jù)源呻粹、構(gòu)造報(bào)文到踏、序列化和發(fā)送。相對(duì)來(lái)說(shuō)構(gòu)造報(bào)文和序列化比較繁瑣尚猿,基于RFC定義的細(xì)節(jié)進(jìn)行窝稿。</br>

5.2 RTCP報(bào)文接收和解析

</br>
接收端的RTCP報(bào)文接收和解析過(guò)程如圖5所示。</br>

圖5 RTCP報(bào)文接收和解析

在接收端凿掂,RTCP報(bào)文的接收流程和RTP一樣伴榔,經(jīng)過(guò)網(wǎng)絡(luò)接收之后到達(dá)Call對(duì)象,進(jìn)而通過(guò)SSRC找到VideoReceiveStream庄萎,繼而到達(dá)RtpStreamReceiver踪少。接下來(lái)RTCP報(bào)文的解析和反饋操作都在ModuleRtpRtcpImpl::IncomingRtcpPacket()函數(shù)中完成。該函數(shù)首先調(diào)用RTCPReceiver::IncomingRtcpPacket()解析RTCP報(bào)文糠涛,得到RTCPPacketInformation對(duì)象援奢,然后調(diào)用 TriggerCallbacksFromRTCPPacket(),觸發(fā)注冊(cè)在此處的各路觀察者執(zhí)行回調(diào)操作忍捡。</br>

RTCPReceiver::IncomingRtcpPacket()使用RTCPParser解析組合報(bào)文集漾,針對(duì)每一種報(bào)文類型,調(diào)用對(duì)應(yīng)的處理函數(shù)(如處理SDES的HandleSDES函數(shù))砸脊,反序列化后拿到報(bào)文的描述結(jié)構(gòu)具篇。最后所有報(bào)文綜合在一起形成RTCPPacketInformation對(duì)象。該對(duì)象接下來(lái)作為參數(shù)調(diào)用TriggerCallbacksFromRTCPPacket()函數(shù)觸發(fā)回調(diào)操作凌埂,如處理NACK的回調(diào)驱显,處理SLI的回調(diào),處理REMB的回調(diào)瞳抓,等等埃疫。這些回調(diào)在各自模塊控制流媒體數(shù)據(jù)的編碼、發(fā)送孩哑、碼率等服務(wù)質(zhì)量保證栓霜,這也是RTCP報(bào)文最終起作用的地方。</br>

至此臭笆,我們分析了RTCP報(bào)文發(fā)送和接收的整個(gè)流程叙淌。</br>

六 總結(jié)

</br>
本文在深入分析WebRTC源代碼的基礎(chǔ)上,結(jié)合流程圖描述出RTP/RTCP模塊的實(shí)現(xiàn)流程愁铺,在關(guān)鍵問(wèn)題上(如RTCP報(bào)文的數(shù)據(jù)來(lái)源)進(jìn)行深入細(xì)致的研究鹰霍。為進(jìn)一步深入掌握WebRTC的實(shí)現(xiàn)原理和細(xì)節(jié)打下良好基礎(chǔ)。</br>
</br>

參考文獻(xiàn)

</br>
[1] RFC3550 - RTP: A Transport Protocol for Real-Time Applications
https://www.ietf.org/rfc/rfc3550.txt
[2] 超越RFC3550 - RTP/RTCP協(xié)議族分析 : http://www.reibang.com/p/e5e21aeb219f

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載茵乱,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者茂洒。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瓶竭,隨后出現(xiàn)的幾起案子督勺,更是在濱河造成了極大的恐慌渠羞,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件智哀,死亡現(xiàn)場(chǎng)離奇詭異次询,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)瓷叫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)屯吊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人摹菠,你說(shuō)我怎么就攤上這事盒卸。” “怎么了次氨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵蔽介,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我煮寡,道長(zhǎng)虹蓄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任洲押,我火速辦了婚禮武花,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杈帐。我一直安慰自己,他們只是感情好专钉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布挑童。 她就那樣靜靜地躺著,像睡著了一般跃须。 火紅的嫁衣襯著肌膚如雪站叼。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天菇民,我揣著相機(jī)與錄音尽楔,去河邊找鬼。 笑死第练,一個(gè)胖子當(dāng)著我的面吹牛阔馋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播娇掏,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼呕寝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了婴梧?” 一聲冷哼從身側(cè)響起下梢,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤客蹋,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后孽江,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體讶坯,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年岗屏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辆琅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡担汤,死狀恐怖涎跨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情崭歧,我是刑警寧澤隅很,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站率碾,受9級(jí)特大地震影響叔营,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜所宰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一绒尊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仔粥,春花似錦婴谱、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至麦向,卻和暖如春瘟裸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诵竭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工话告, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卵慰。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓沙郭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親呵燕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棠绘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容