NuPlayer:RTP/RTSP

RTSP SDP RTP/RTCP

介绍应用层 RTSP、SDP;

传输层 RTP、TCP、UDP;

网络层 IPSDP:

(1)SDP(Session Description Protocol)是服务器端生成的描述媒体文件的编码信息以及所在服务器的链接等信息的文件,客户端通过它来设置播放软件的参数。SDP只是一种用于会话描述的协议,它并不是一种传输协议,只是用于在不同传输协议之间传递消息的通知协议,其主要目的是解决多媒体会话通知、邀请和另外一些媒体会话的初始化工作。

(2) SDP内容包括:会话名称和目的、会话持续时间、媒体类(音频、视频等)、传输协议(RTP/UDP/IP,H.320等)、媒体编码格式(MPEG4、H.263、H.264等)、接收媒体的相关信息端口和格式等。

RTSP:

(1)RTSP是应用级协议,用于流媒体服务器和终端播放器之间的媒体流会话的建立和控制。RTSP本身不被用于传输媒体数据,而是用于控制媒体流播放的过程,如会话建立、暂停、停止、快进、快退、录制等。媒体传输协议和相应的参数在会话建立过程中双方协商确定,一般采用RTP协议。RTSP是文本协议,其功能和HTTP及SIP类似,不同之处是RTSP及SIP本身不传输媒体流数据,而HTTP可以。

(2) RTSP可以承载在TCP或UDP之上(一般为TCP),端口号为554。RTSP通过定义一些“Method”来实现会话的控制,其主要的Mothod有:DESCRIBE、SETUP、PLAY、PAUSE、RECORD、REDIRECT、TEARDOWN等。同时,RTSP通过会话描述协议(SDP)来协商双方的媒体格式、传输协议等。

RTP/RTCP:

(1)整个RTP 协议由两个密切相关的部分组成:RTP 数据协议和RTP控制协议,当应用程序开始一个RTP会话时将使用两对端口:一对用于RTP,另外一对用于RTCP。RTP是针对多媒体数据流的传输协议,能够提供时间信息并提供流同步,但本身并不能提供可靠的传送机制,也不提供流量控制或拥塞控制,它依靠RTCP提供这些服务。RTP通常采用UDP来传送数据。

(2) RTCP和RTP一起提供流量控制和拥塞控制服务,RTCP的主要功能是为数据的传送情况提供反馈。在RTP会话期间,各参与者周期性..传送RTCP包,RTCP包中含有已发送的数据包数量、丢失的数据包数量等统计信息,服务器可以据这些信息动态收变传输速率,甚至收变有效负荷的类。RTP和RTCP配合使用,能够以有效的反馈和最小的开销使传输效率最佳化。

RTP/RTSP/RTCP的区别用一句简单的话总结:RTSP发起/终结流媒体、RTP传输流媒体数据、RTCP对RTP进行控制,同步。

•RTP:实时传输协议(Real-time Transport Protocol)

RTP/RTCP是实际传输数据的协议oRTP传输音频/视频数据,如果是PLAY,Server发送到Client端,如果是RECORD,可以由Client发送到Server

整个RTP协议由两个密切相关的部分组成:RTP数据协议和RTP控制协议(即RTCP)

•RTSP:实时流协议(Real Time Streaming Protocol,RTSP)

RTSP的请求主要有DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN,OPTIONS等,顾名思义可以知道起对话和控制作用

RTSP的对话过程中SETUP可以确定RTP/RTCP使用的端口,PLAY/PAUSE/TEARDOWN可以开始或者停止RTP的发送,等等

•RTCP:

RTP/RTCP是实际传输数据的协议

RTCP包括Sender Report和Receiver Report,用来进行音频/视频的同步以及其他用途,是一种控制协议

以下是每个协议的概要介绍:

一、RTP数据协议

RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部(Header)和负载(Payload)两个部分组成,其中头部前12个字节的含义是固定的,而负载则可以是音频或者视频数据。其中比较重要的几个域及其意义如下:

•CSRC记数(CC):表示CSRC标识的数目。CSRC标识紧跟在RTP固定头部之后,用来表示RTP数据报的来源,RTP协议允许在同一个会话中存在多个数据源,它们可以通过RTP混合器合并为一个数据源。例如,可以产生一个 CSRC列表来表示一个电话会议,该会议通过一个RTP混合器将所有讲话者的语音数据组合为一个RTP数据源。

•负载类型(PT):标明RTP负载的格式,包括所采用的编码算法、采样频率、承载通道等。例如,类型2表明该RTP数据包中承载的是用ITU G.721算法编码的语音数据,采样频率为8000Hz,并且采用单声道。

•序列号:用来为接收方提供探测数据丢失的方法,但如何处理丢失的数据则是应用程序自己的事情,RTP协议本身并不负责数据的重传。

•时间戳:记录了负载中第一个字节的采样时间,接收方能够时间戳能够确定数据的到达是否受到了延迟抖动的影响,但具体如何来补偿延迟抖动则是应用程序自己的事情。

从RTP数据报的格式不难看出,它包含了传输媒体的类型、格式、序列号、时间戳以及是否有附加数据等信息,这些都为实时的流媒体传输提供了相应的基础。RTP协议的目的是提供实时数据(如交互式的音频和视频)的端到端传输服务,因此在RTP中没有连接的概念,它可以建立在底层的面向连接或面向非连接的传输协议之上;RTP也不依赖于特别的网络地址格式,而仅仅只需要底层传输协议支持组帧(Framing)和分段(Segmentation)就足够了;另外RTP本身还不提供任何可靠性机制,这些都要由传输协议或者应用程序自己来保证。在典型的应用场合下,RTP一般是在传输协议之上作为应用程序的一部分加以实现的,

二、RTCP控制协议

RTCP控制协议需要与RTP数据协议一起配合使用,当应用程序启动一个RTP会话时将同时占用两个端口,分别供RTP和RTCP使用。RTP本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完成。通常RTCP会采用与RTP相同的分发机制,向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据,从中获取会话参与者的相关资料,以及网络状况、分组丢失概率等反馈信息,从而能够对服务质量进行控制或者对网络状况进行诊断。

RTCP协议的功能是通过不同的RTCP数据报来实现的,主要有如下几种类型:

•SR:发送端报告,所谓发送端是指发出RTP数据报的应用程序或者终端,发送端同时也可以是接收端。

•RR:接收端报告,所谓接收端是指仅接收但不发送RTP数据报的应用程序或者终端。

•SDES:源描述,主要功能是作为会话成员有关标识信息的载体,如用户名、邮件地址、电话号码等,此外还具有向会话成员传达会话控制信息的功能。

•BYE:通知离开,主要功能是指示某一个或者几个源不再有效,即通知会话中的其他成员自己将退出会话。

•APP:由应用程序自己定义,解决了RTCP的扩展性问题,并且为协议的实现者提供了很大的灵活性。

RTCP数据报携带有服务质量监控的必要信息,能够对服务质量进行动态的调整,并能够对网络拥塞进行有效的控制。由于RTCP数据报采用的是多播方式,因此会话中的所有成员都可以通过RTCP数据报返回的控制信息,来了解其他参与者的当前情况。


在一个典型的应用场合下,发送媒体流的应用程序将周期性地产生发送端报告SR,该RTCP数据报含有不同媒体流间的同步信息,以及已经发送的数据报和字节的计数,接收端根据这些信息可以估计出实际的数据传输速率。另一方面,接收端会向所有已知的发送端发送接收端报告RR,该RTCP数据报含有已接收数据报的最大序列号、丢失的数据报数目、延时抖动和时间戳等重要信息,发送端应用根据这些信息可以估计出往返时延,并且可以根据数据报丢失概率和时延抖动情况动态调整发送速率,以改善网络拥塞状况,或者根据网络状况平滑地调整应用程序的服务质量。

三、RTSP实时流协议

作为一个应用层协议,RTSP提供了一个可供扩展的框架,它的意义在于使得实时流媒体数据的受控和点播变得可能。总的说来,RTSP是一个流媒体表示协议,主要用来控制具有实时特性的数据发送,但它本身并不传输数据,而是必须依赖于下层传输协议所提供的某些服务。RTSP可以对流媒体提供诸如播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与RTP间的交互操作。

由RTSP控制的媒体流集合可以用表示描述(Presentation Description)来定义,所谓表示是指流媒体服务器提供给客户机的一个或者多个媒体流的集合,而表示描述则包含了一个表示中各个媒体流的相关信息,如数据编码/解码算法、网络地址、媒体流的内容等。虽然RTSP服务器同样也使用标识符来区别每一流连接会话(Session),但RTSP连接并没有被绑定到传输层连接(如TCP等),也就是说在整个 RTSP连接期间,RTSP用户可打开或者关闭多个对RTSP服务器的可靠传输连接以发出RTSP请求。此外,RTSP连接也可以基于面向无连接的传输协议(如UDP等)。

RTSP协议目前支持以下操作:

•检索媒体:允许用户通过HTTP或者其它方法向媒体服务器提交一个表示描述。如表示是组播的,则表示描述就包含用于该媒体流的组播地址和端口号;如果表示是单播的,为了安全在表示描述中应该只提供目的地址。

•邀请加入:媒体服务器可以被邀请参加正在进行的会议,或者在表示中回放媒体,或者在表示中录制全部媒体或其子集,非常适合于分布式教学。

•添加媒体:通知用户新加入的可利用媒体流,这对现场讲座来讲显得尤其有用。RTSP请求也可以交由代理、通道或者缓存来进行处理。

RTSP消息格式: RTSP的消息有两大类,一是请求消息(request),一是回应消息(response),两种消息的格式不同.

请求消息:

方法 URI RTSP版本 CR LF

消息头 CR LF CR LF

消息体 CR LF

其中方法包括OPTION回应中所有的命令,URI是接受方的地址,例如 :

rtsp://192.168.20.136

RTSP版本一般都是 RTSP/1.0.每行后面的CR LF表示回车换行,需要接受端有相应的解析,最后一个消息头需要有两个CR LF

回应消息:

RTSP版本 状态码 解释 CR LF

消息头 CR LF CR LF

消息体 CR LF

其中RTSP版本一般都是RTSP/1.0,状态码是一个数值,200表示成功,解释是与状态码对应的文本解释.


简单的rtsp交互过程: C表示rtsp客户端,S表示rtsp服务端

1.C->S:OPTION request //询问S有哪些方法可用

1.S->C:OPTION response //S回应信息中包括提供的所有可用方法

2.C->S:DESCRIBE request //要求得到S提供的媒体初始化描述信息

2.S->C:DESCRIBE response //S回应媒体初始化描述信息,主要是sdp

3.C->S:SETUP request //设置会话的属性,以及传输模式,提醒S建立会话

3.S->C:SETUP response //S建立会话,返回会话标识符,以及会话相关信息

4.C->S:PLAY request //C请求播放

4.S->C:PLAY response //S回应该请求的信息

S->C:发送流媒体数据

5.C->S:TEARDOWN request //C请求关闭会话

5.S->C:TEARDOWN response //S回应该请求

上述的过程是标准的、友好的rtsp流程,但实际的需求中并不一定按部就班来。其中第3和4步是必需的!第一步,只要服务器客户端约定好,有哪些方法可用,则option请求可以不要。第二步,如果我们有其他途径得到媒体初始化描述信息(比如http请求等等),则我们也不需要通过rtsp中的describe请求来完成。第五步,可以根据系统需求的设计来决定是否需要。

rtsp中常用方法:

1.OPTION

目的是得到服务器提供的可用方法:

 OPTIONS rtsp://192.168.20.136:5000/xxx666 RTSP/1.0

CSeq: 1 //每个消息都有序号来标记,第一个包通常是option请求消息

User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10)

服务器的回应信息包括提供的一些方法,例如:

 RTSP/1.0 200 OK Server: UServer 0.9.7_rc1

Cseq: 1 //每个回应消息的cseq数值和请求消息的cseq相对应

Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, SCALE,GET_PARAMETER //服务器提供的可用的方法

2.DESCRIBE

C向S发起DESCRIBE请求,为了得到会话描述信息(SDP):

 DESCRIBE rtsp://192.168.20.136:5000/xxx666 RTSP/1.0

CSeq: 2

token:

 Accept: application/sdp User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10)

服务器回应一些对此会话的描述信息(sdp):

RTSP/1.0 200 OK

Server: UServer 0.9.7_rc1

Cseq: 2

x-prev-url: rtsp://192.168.20.136:5000

x-next-url: rtsp://192.168.20.136:5000

x-Accept-Retransmit: our-retransmit

x-Accept-Dynamic-Rate: 1

Cache-Control: must-revalidate

Last-Modified: Fri, 10 Nov 2006 12:34:38 GMT

Date: Fri, 10 Nov 2006 12:34:38 GMT

Expires: Fri, 10 Nov 2006 12:34:38 GMT

Content-Base: rtsp://192.168.20.136:5000/xxx666/

Content-Length: 344

Content-Type: application/sdp

v=0 //以下都是sdp信息

o=OnewaveUServerNG 1451516402 1025358037 IN IP4 192.168.20.136

s=/xxx666

u=http:///

e=admin@

c=IN IP4 0.0.0.0

t=0 0

a=isma-compliance:1,1.0,1 a=range:

npt=0-

m=video 0 RTP/AVP 96 //m表示媒体描述,下面是对会话中视频通道的媒体描述

 a=rtpmap:96 MP4V-ES/90000

a=fmtp:96 profile-level-id=245; config=000001B0F5000001B509000001000000012000C888B0E0E0FA62D089028307 a=control:trackID=0//trackID=0表示视频流用的是通道0

3.SETUP 客户端提醒服务器建立会话,并确定传输模式:

 SETUP rtsp://192.168.20.136:5000/xxx666/trackID=0 RTSP/1.0

CSeq: 3

Transport: RTP/AVP/TCP;unicast;interleaved=0-1

User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10)

 //uri中带有trackID=0,表示对该通道进行设置。Transport参数设置了传输模式,包的结构。接下来的数据包头部第二个字节位置就是interleaved,它的值是每个通道都不同的,trackID=0的interleaved值有两个0或1,0表示rtp包,1表示rtcp包,接受端根据interleaved的值来区别是哪种数据包。

服务器回应信息:

 RTSP/1.0 200 OK Server: UServer 0.9.7_rc1 Cseq: 3 Session: 6310936469860791894

//服务器回应的会话标识符

Cache-Control: no-cache

Transport: RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=6B8B4567

4.PLAY 客户端发送播放请求:

PLAY rtsp://192.168.20.136:5000/xxx666 RTSP/1.0

CSeq: 4

Session: 6310936469860791894

Range: npt=0.000- //设置播放时间的范围

User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10)

服务器回应信息:

RTSP/1.0 200 OK

Server: UServer 0.9.7_rc1

Cseq: 4

Session: 6310936469860791894

Range: npt=0.000000-

RTP-Info: url=trackID=0;

seq=17040;rtptime=1467265309 //seq和rtptime都是rtp包中的信息

5.TEARDOWN 客户端发起关闭请求:

TEARDOWN rtsp://192.168.20.136:5000/xxx666 RTSP/1.0

CSeq: 5

Session: 6310936469860791894

User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10)

服务器回应:

RTSP/1.0 200 OK

Server: UServer 0.9.7_rc1

Cseq: 5

Session: 6310936469860791894

Connection: Close

以上方法都是交互过程中最为常用的,其它还有一些重要的方法如 get/set_parameter,pause,redirect等等 ps: sdp的格式 v=o=s=i=u=e=p=c=b=:t=r=z=.... k=k=:a=a=:m=o = (所有者/创建者和会话标识符)

s = (会话名称)

i = * (会话信息)

u = * (URI 描述)

e = * (Email 地址)

p = * (电话号码)

c = * (连接信息)

b = * (带宽信息)

z = * (时间区域调整)

k = * (加密密钥)

a = * (0 个或多个会话属性行)

时间描述:

t = (会话活动时间)

r = * (0或多次重复次数)

媒体描述:

m = (媒体名称和传输地址)

i = * (媒体标题)

c = * (连接信息 — 如果包含在会话层则该字段可选)

b = * (带宽信息)

k = * (加密密钥)

a = * (0 个或多个媒体属性行)

RTSP点播消息流程实例(客户端:VLC, RTSP服务器:LIVE555 Media Server)

1)C(Client)-> M(Media Server)

OPTIONS rtsp://192.168.1.109/1.mpg RTSP/1.0

CSeq: 1

user-Agent: VLC media player(LIVE555 Streaming Media v2007.02.20)

1)M -> C

RTSP/1.0 200 OK

CSeq: 1

Date: wed, Feb 20 2008 07:13:24 GMT

Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE

2)C -> M

DESCRIBE rtsp://192.168.1.109/1.mpg RTSP/1.0

CSeq: 2

Accept: application/sdp

User-Agent: VLC media player(LIVE555 Streaming Media v2007.02.20)

2)M -> C

RTSP/1.0 200 OK

CSeq: 2

Date: wed, Feb 20 2008 07:13:25 GMT

Content-Base: rtsp://192.168.1.109/1.mpg/

Content-type: application/sdp

Content-length: 447

v=0

o =- 2284269756 1 IN IP4 192.168.1.109

s=MPEG-1 or 2 program Stream, streamed by the LIVE555 Media Server

i=1.mpg

t=0 0

a=tool:LIVE555 Streaming Media v2008.02.08

a=type:broadcast

a=control:*

a=range:npt=0-66.181

a=x-qt-text-nam:MPEG-1 or Program Stream, streamed by the LIVE555 Media Server

a=x-qt-text-inf:1.mpg

m=video 0 RTP/AVP 32

c=IN IP4 0.0.0.0

a=control:track1

m=audio 0 RTP/AVP 14

c=IN IP4 0.0.0.0

a=control:track2

3)C -> M

SETUP rtsp://192.168.1.109/1.mpg/track1 RTSP/1.0

CSeq: 3

Transport: RTP/AVP; unicast;client_port=1112-1113

User-Agent: VLC media player(LIVE555 Streaming Media v2007.02.20)

3)M -> C

RTSP/1.0 200 OK

CSeq: 3

Date: wed, Feb 20 2008 07:13:25 GMT

Transport: RTP/AVP;unicast;destination=192.168.1.222;source=192.168.1.109;client_port=1112-1113;server_port=6970-6971

Session: 3

4)C -> M

SETUP rtsp://192.168.1.109/1.mpg/track2 RTSP/1.0

CSeq: 4

Transport: RTP/AVP; unicast;client_port=1114-1115

Session: 3

User-Agent: VLC media player(LIVE555 Streaming Media v2007.02.20)

4)M -> C

RTSP/1.0 200 OK

CSeq: 4

Date: wed, Feb 20 2008 07:13:25 GMT

Transport: RTP/AVP;unicast;destination=192.168.1.222;source=192.168.1.109;client_port=1114-1115;server_port=6972-6973

Session: 3

5)C -> M

PLAY rtsp://192.168.1.109/1.mpg/ RTSP/1.0

CSeq: 5

Session: 3

Range: npt=0.000-

User-Agent: VLC media player(LIVE555 Streaming Media v2007.02.20)

5)M -> C

RTSP/1.0 200 OK

CSeq: 5

Range: npt=0.000-

Session: 3

RTP-Info: url=rtsp://192.168.1.109/1.mpg/track1;seq=9200;rtptime=214793785,url=rtsp://192.168.1.109/1.mpg/track2;seq=12770;rtptime=31721

(开始传输流媒体...)

一、整体框架图

Android中基于NuPlayer的RTSP框架如下图所示。

整个图主要分为两个部分,一部分是NuPlayer的架构,另一部分则是实现了基于RTSP的流媒体播放功能,即RTSPSource。当然还有一些其他的Source,如图中的HTTPLiveSource,还有图中没有画出的GenericSource、StreamingSource等,他们是并列关系,实现了不同的播放功能。

二、NuPlayer架构

1、NuPlayerDriver是对NuPlayer的封装,与NuPlayerDriver处于并列位置的是StagefrightPlayer,他们都继承MediaPlayerInterface接口。通过NuPlayer来实现播放的功能。

2、NuPlayer真正实现了播放的功能,通过各个Source的接口来得到数据流的信息和解码数据本身。

三、RTSP功能实现架构(重点中的重点)

1、RTSPSource是NuPlayer架构的Source,给NuPlayer输送媒体所需数据信息和媒体数据。在整个NuPlayer架构中,与RTSPSource并列的Source有HTTPLiveSource、GenericSource、StreamingSource,还有一个MP4Source,他们都继承NuPlayer::Source。

2、MyHandler是RTSP的核心,其中包含ARTSPConnection和ARTPConnection两大部分。MyHandler负责向Server端发送Request和处理Response,并负责将待解码的媒体数据传送给RTSPSource。

3、AnotherPacketSource在RTSPSource中作为mAudioTrack和mVideoTrack,他虽然继承了MediaSource接口,但是并没有使用read来读数据,而是通过dequeueAccessUnit接口来获得数据。RTSPSource通过调用queueAccessUnit结构将数据保存到这里。

4、ARTSPConnection负责维护RTSP的socket,发送Request,循环接收Server端数据,响应Server的Request。这里只是接收Response,真正的处理在MyHandler里。

5、ARTPConnection负责维护RTP和RTCP的socket,接收RTP和RTCP包,周期性发送RTCP包。需要说明的一点是,如果传输RTP和RTCP数据使用的是TCP,那么会共用RTSP的socket;如果用的是UDP,那么针对每个stream都会创建两个socket,一个用于传输RTP数据,一个用于传输RTCP数据。

6、ARTPSource,每个RTP数据流都有一个ARTPSource,后者会创建一个ARTPAssembler。依据处理数据流的压缩格式,实例化对应格式的Assembler。在ARTPSource中实现的一个最主要而且重要的功能就是根据SeqNum对RTP包进行排序。

7、ARTPAssembler对ARTPConnection接收到的数据进行处理,说的简单一点就将接收到的媒体数据进行重组,以满足解码器的要求。如AVC数据,他会把单一NAL,NAL分片和复合NAL分别处理后,都以单独NAL的形式回调传给RTSPSource,存放在AnotherPacketSource中,供decoder端使用。目前支持的Assembler有一下几种,他们都继承ARTPAssembler。

(1)AAVCAssembler

(2)AMPEG4AudioAssembler

(3)AH263Assembler

(4)AAMRAssembler

(5)AMPEG4ElementaryAssembler

(6)ARawAudioAssembler

(7)AMPEG2TSAssembler

8、APacketSource用来包存和设置每个stream的属性。针对每个stream都会创建一个APacketSource

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345