【发布时间】:2019-02-17 18:48:48
【问题描述】:
我正在使用 FFMPEG 解码 H264(或 H265)RTSP 流。
我的系统有两个软件:服务器和客户端
Server: Read frames from RTSP stream --> Forward frames to Client
Client: Receive frames from Server --> Decode --> Render
我已经实现并且工作正常,但是有一个案例使我的系统工作不好。那是当服务器 - 客户端的互联网速度很慢时,帧无法实时传输到客户端。
目前,当队列达到计数限制时,我通过跳过一些帧(不发送到客户端)来处理这个问题。以下是我的总结代码
//At Server Software (include 2 threads A and B)
//Thread A: Read AVPacket and forward to Client
while(true)
{
AVPacket packet;
av_init_packet(&packet);
packet.size = 0;
packet.data = NULL;
int ret = AVERROR(EAGAIN);
while (AVERROR(EAGAIN) == ret)
ret = av_read_frame(pFormatCtx, &packet);
if(packet.size > 0)
{
if(mySendQueue.count < 120) //limit 120 packet in queue
mySendQueue.Enqueue(packet); ////Thread B will read from this queue, to send packets to Client via TCP socket
else
;//SkipThisFrame ***: No send
}
}
//Thread B: Send To Client via TCP Socket
While(true)
{
AVPacket packet;
if(mySendQueue.Dequeue(packet))
{
SendPacketToClient(packet);
}
}
//At Server Software : Receive AVPacket from Server --> Decode --> Render
While(true)
{
AVPacket packet;
AVFrame frame;
ReadPacketFromServer(packet);
if (av_decode_asyn(pCodecCtx, &frame, &frameFinished, &packet) == RS_OK)
{
if (frameFinished)
{
RenderFrame(frame);
}
}
}
UINT32 __clrcall av_decode_asyn(AVCodecContext *pCodecCtx, AVFrame *frame, int *frameFinished, AVPacket *packet)
{
int ret = -1;
*frameFinished = 0;
if (packet)
{
ret = avcodec_send_packet(pCodecCtx, packet);
// In particular, we don't expect AVERROR(EAGAIN), because we read all
// decoded frames with avcodec_receive_frame() until done.
if (ret < 0 && ret != AVERROR_EOF)
return RS_NOT_OK;
}
ret = avcodec_receive_frame(pCodecCtx, frame);
if (ret < 0 && ret != AVERROR(EAGAIN))
{
return RS_NOT_OK;
}
if (ret >= 0)
*frameFinished = 1;
return RS_OK;
}
我的问题是关注SkipThisFrame ***这行代码,这个算法连续跳帧,可能导致Client端的解码器出现意外错误或者Crash?
而当这样跳帧时,使Client Render 帧不正常?
有人打电话告诉我在我的情况下跳帧的正确算法吗?
非常感谢!
【问题讨论】:
-
这个逻辑不应该是
Server: Store "incoming" frames from RTSP stream --> Forward "existing" frames to Client吗? -
@VC.One:谢谢!我明白你说的,但是当互联网很慢时,我必须跳过帧才能在客户端上进行实时渲染。我认为哪种跳帧算法最好
-
正如其他人已经说过的那样,您不能跳过 h264 流中的解码帧,因为 P 帧(预测)只包含与最后重建的帧的差异。但是,您可以做的是跳过在有问题的显示器上显示帧并限制感知的 fps。