c++ - FFmpeg:解码从 UDP 套接字接收到的 AVPackets
问题描述
我正在尝试通过 UDP 将使用 FFmpeg 编码的视频帧从 Unity 游戏流式传输到客户端 UI。具体来说,我从服务器发送 AVPackets(据我所知,其中包含压缩帧),然后在客户端提取如下:
inline UDPpacket* SDLGameClient::receiveData()
{
if(SDLNet_UDP_Recv(socket, packet))
return packet;
else
return NULL;
}
int main()
{
...
// Initialize UDP
...
UDPpacket *udpPacket;
int i = 0;
for(;;)
{
udpPacket = client->receiveData();
if(udpPacket != nullptr)
{
i++;
std::cout << "Packet " << i << " received!" << std::endl;
AVPacket packet;
av_init_packet(&packet);
packet.data = new uint8_t[udpPacket->len];
memcpy(packet.data, udpPacket->data, udpPacket->len);
packet.size = udpPacket->len;
...
为了实现联网,我使用了 SDL_net 库。分段、发送和接收数据包似乎没有任何问题。我的问题是,如何解码传入的 AVPackets 并将 Unity 中记录的帧流式传输到客户端?我知道我需要使用avcodec_send_packet
andavcodec_receive_frame
进行解码(因为avcodec_decode_video2
在许多示例解码代码中使用的 已弃用),但是当我执行以下操作时:
int ret = avcodec_send_packet(codecContext, &packet);
if(ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
std::cout << "avcodec_send_packet: " << ret << std::endl;
else
{
while(ret >= 0)
{
ret = avcodec_receive_frame(codecContext, frame);
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
std::cout << "avcodec_receive_frame: " << ret << std::endl;
std::cout << "Frame: " << codecContext->frame_number << std::endl;
}
}
av_packet_unref(packet);
ret 总是返回一个负值(-22),所以可能是 AVPackets 出了点问题,或者我发送帧的速度太快了,我真的不知道:/
提前感谢您的帮助!
解决方案
-22表示-EINVAL,无效参数。您通常可以检查 ffmpeg 错误日志消息以获取更多详细信息。
我的猜测是你的数据包仍然是碎片化的,但是 avcodec_send_packet() 期望 AVPacket 总是包含一个完整的帧。根据所涉及的编解码器,您应该考虑使用 AVParser 来恢复帧或在 UDP 分段之前对数据包进行帧,因此您可以自己恢复帧。
推荐阅读
- variables - 如何基于另一个不同长度的数据集在 R 中创建变量
- ios - 打开相机时应用程序崩溃
- java - 查找一个项目在数组中出现了多少次 = 解释代码
- javascript - ReferenceError:确认未定义
- android - 同步“com.google.firebase:firebase-analytics@17.2.2”时生成错误
- macos - Macbook上的Powershell脚本返回错误
- python - os.walk() 在 Windows 10 上为带有重音字母的文件生成无效路径
- c++ - C2679 二进制“<<”:未找到采用右侧操作数类型的运算符
- java - 如何在 Spring Boot 中更新单个表列而不更新其余属性?
- c# - 如何使用 Moq 使用 lambda 表达式模拟服务调用