如何实现live555中接收的视频数据是完整帧

时间:2022-06-27 03:58:50
实现了摄像头采集视频并以RTSP流发送出去,用vlc是可以播放这个RTSP流的,现在可以基于live555接收RTSP视频流保存为一个264文件,并基于ffmpeg解码这个文件在浏览器上显示出来。现在需要不保存为文件,直接取出一帧数据传给ffmpeg解码。
在FileSink的addData中fwrite函数写入数据到文件,但是strlen传给fwrite的data数据时大时小,小的时候为零,大的时候10000多;
可以看出afterGettingFrame中的adddata调用写入了图像数据,因为注销这个adddata,过10几秒写出的文件只有几K,不注销时写出的有10M左右,但是它写入的fBuffer也是时大时小,小的时候为零,大的时候10000多。
同时continuePlaying中fSource->getNextFrame函数,fBuffer也是跟上面一样,时大时小。

这三个个地方的data和fBuffer传过去解码,在解码函数avcodec_decode_video中都显示:[h264 @ 65E8EAC0] no frame!看起来是没有得到完整的一帧数据。

现在怎么样在这里得到完整的一帧图像数据,以便传过去解码,求指导,不胜感激。

9 个解决方案

#1


filesink获取的就是1帧数据,h264编码,live555没加0 0 0 1

#2


在fileSink的afternextframe()中,通过adddata()把buffer写到指定的文件中。
afternextframe()中的就是一个完整的帧数据。

#3


引用 2 楼  的回复:
在fileSink的afternextframe()中,通过adddata()把buffer写到指定的文件中。
afternextframe()中的就是一个完整的帧数据。


我在linux下grep了一下,live555里面没有afternextframe这个函数,getnextframe倒是有的,不过这里的fBuffer也是一会基本为零,一会10000多,有点困惑

#4


引用 1 楼  的回复:
filesink获取的就是1帧数据,h264编码,live555没加0 0 0 1


我在adddata的fBuffer前加上了0x00,0x00,0x00,0x01,传过去一样的情况,主要是adddata进去的数据有时大小只有几十,有时又有10000多;
尝试根据struct timeval presentationTime来判断时间,把几次接收到presentationTime相同的数据写入同一个buffer然后解码,还是说no frame

#5


数据大小怎么能用strlen来取呢?遇到0x00就截断了。

#6


楼主现在解决了吗?我也很想知道。

#7


buf的最大容量为20000,读取数据时就会用这个buf来接收,每接收一次buf的容量就会变小,如果你每次都打印fMaxSize的值,你就会发现它是递减的,fMaxSize其实就是buf的剩余容量,所以它递减,每次也是依据这个容量来接收数据,当buf满了之后,会把这个满的buf中的数据放到待处理链表中,同时分配一个新的buf,大小依然是20000.所以每次读取的数据并不能保证是完整的一帧。
avcodec_decode_video解码的结果为no frame是正常的,你只需要把这些还未解码成功的数据数据保存下来,和下次到达的数据再一起传给解码器,解码器就会自己查找是否有完整帧,若无,继续上面的操作,直到有完整帧,删掉那一帧的数据,接下来重复就可以了。
如果你想手动判定h264的一帧也可以,只需要寻找数据里的00 00 00 01,对于P帧,都是以00 00 00 01开头,到下一个00 00 00 01结束(这是下一帧的开头),然后把这部分数据拿出来传给解码器解码也是可以的。

#8


live555 的sink中有 // Request the next frame of data from our input source.  "afterGettingFrame()" will get called later, when it arrives:
fSource->getNextFrame(fReceiveBuffer, RTPMEDAA_SINK_RECEIVE_BUFFER_SIZE,
afterGettingFrame, this,
onSourceClosure, this);

fReceiveBuffer中就是Buff,如果服务端sps,pps,i帧 是分开发包的话,客户端要自己组包,组成一帧,如果不是分开发,直接加00 00 00 01 ,就是一帧完整数据,交给ffmpeg解码就行,具体看我的博客;
http://blog.csdn.net/smilestone_322?viewmode=contents

#9


该回复于2015-03-20 15:23:43被管理员删除

#1


filesink获取的就是1帧数据,h264编码,live555没加0 0 0 1

#2


在fileSink的afternextframe()中,通过adddata()把buffer写到指定的文件中。
afternextframe()中的就是一个完整的帧数据。

#3


引用 2 楼  的回复:
在fileSink的afternextframe()中,通过adddata()把buffer写到指定的文件中。
afternextframe()中的就是一个完整的帧数据。


我在linux下grep了一下,live555里面没有afternextframe这个函数,getnextframe倒是有的,不过这里的fBuffer也是一会基本为零,一会10000多,有点困惑

#4


引用 1 楼  的回复:
filesink获取的就是1帧数据,h264编码,live555没加0 0 0 1


我在adddata的fBuffer前加上了0x00,0x00,0x00,0x01,传过去一样的情况,主要是adddata进去的数据有时大小只有几十,有时又有10000多;
尝试根据struct timeval presentationTime来判断时间,把几次接收到presentationTime相同的数据写入同一个buffer然后解码,还是说no frame

#5


数据大小怎么能用strlen来取呢?遇到0x00就截断了。

#6


楼主现在解决了吗?我也很想知道。

#7


buf的最大容量为20000,读取数据时就会用这个buf来接收,每接收一次buf的容量就会变小,如果你每次都打印fMaxSize的值,你就会发现它是递减的,fMaxSize其实就是buf的剩余容量,所以它递减,每次也是依据这个容量来接收数据,当buf满了之后,会把这个满的buf中的数据放到待处理链表中,同时分配一个新的buf,大小依然是20000.所以每次读取的数据并不能保证是完整的一帧。
avcodec_decode_video解码的结果为no frame是正常的,你只需要把这些还未解码成功的数据数据保存下来,和下次到达的数据再一起传给解码器,解码器就会自己查找是否有完整帧,若无,继续上面的操作,直到有完整帧,删掉那一帧的数据,接下来重复就可以了。
如果你想手动判定h264的一帧也可以,只需要寻找数据里的00 00 00 01,对于P帧,都是以00 00 00 01开头,到下一个00 00 00 01结束(这是下一帧的开头),然后把这部分数据拿出来传给解码器解码也是可以的。

#8


live555 的sink中有 // Request the next frame of data from our input source.  "afterGettingFrame()" will get called later, when it arrives:
fSource->getNextFrame(fReceiveBuffer, RTPMEDAA_SINK_RECEIVE_BUFFER_SIZE,
afterGettingFrame, this,
onSourceClosure, this);

fReceiveBuffer中就是Buff,如果服务端sps,pps,i帧 是分开发包的话,客户端要自己组包,组成一帧,如果不是分开发,直接加00 00 00 01 ,就是一帧完整数据,交给ffmpeg解码就行,具体看我的博客;
http://blog.csdn.net/smilestone_322?viewmode=contents

#9


该回复于2015-03-20 15:23:43被管理员删除