Streaming 使用FFmpeg,如何解码H264数据包
我是FFmpeg新手,正在努力解码H264数据包,这些数据包可以作为uint8_t数组获得 经过多次调查,我认为它应该能够将数组放入如下所示的AVPacket中Streaming 使用FFmpeg,如何解码H264数据包,streaming,ffmpeg,decode,h.264,Streaming,Ffmpeg,Decode,H.264,我是FFmpeg新手,正在努力解码H264数据包,这些数据包可以作为uint8_t数组获得 经过多次调查,我认为它应该能够将数组放入如下所示的AVPacket中 AVPacket *avpkt = (AVPacket *)malloc(sizeof(AVPacket) * 1); av_init_packet(avpkt); avpkt->data = ct; // ct is the array avpkt->length =.... 并通过avcodec\u decod
AVPacket *avpkt = (AVPacket *)malloc(sizeof(AVPacket) * 1);
av_init_packet(avpkt);
avpkt->data = ct; // ct is the array
avpkt->length =....
并通过avcodec\u decode\u video2()
进行解码
代码的一部分类似于:
...
codec = avcodec_find_decoder(CODEC_ID_H264);
gVideoCodecCtx = avcodec_alloc_context();
gFrame = avcodec_alloc_frame();
avcodec_decode_video2(gVideoCodecCtx, gFrame, &frameFinished, packet);
...
我想我已正确设置了所有必需的属性,但此函数仅返回-1
我刚刚发现-1
来自
ret = avctx->codec->decode(avctx, picture, got_picture_ptr, avpkt);
在avcodec\u decode\u video2()中代码>
实际上,我想知道的是如何通过avcodec\u decode\u video2()
解码H264数据包(没有RTP报头)
更新:
好的,我还在努力寻找解决办法。我现在做的是下面的
AVPacket *avpkt = (AVPacket *)malloc(sizeof(AVPacket) * 1);
av_init_packet(avpkt);
avpkt->data = ct; // ct is the array
avpkt->length =....
**该RTP流中的H264流由FU-A编码
接收RTP数据包
查看RTP报头的第二个字节是否大于0,这意味着它是第一个数据包(可能会紧跟其后)
查看下一个RTP数据包的第二个字节是否也大于0,则表示前一帧是完整的NAL,或者如果该帧小于0,则应将该数据包附加到前一个数据包
删除数据包的所有RTP头,使其仅具有类似FU指示符| FU头| NAL
尝试使用avcodec\u decode\u video2()播放它
但它只返回-1
我是否也应该移除FU指示器和收割台
如果您有任何建议,我们将不胜感激。我认为您无法在没有RTP报头的情况下解码H264数据包,因为RTP报头中嵌入了相当多的视频流信息。同时,我猜想所有的视频流信息都有可能被复制到RTP视频包中。因此,它还取决于流是如何生成的
Vibgyor
实际上,我想知道的是,我是否可以通过avcodec_decode_video2()解码H264数据包(没有RTP报头)
如果使用非单个NAL单元模式的打包模式,则在将NAL单元传递给解码器之前,可能需要预处理RTP有效负载(重新组装碎片NAL、拆分聚合NAL)。流中允许的NAL单元类型(STAP、MTAP、FU)取决于打包模式。有关打包模式的更多信息,请阅读
其次,虽然我对FFMPEG不太熟悉,但它可能更像是一个一般的H.264解码问题:在解码其他帧之前,必须始终使用H.264序列(SPS)和图片参数集(PPS)初始化解码器。你做到了吗?这是我的工作代码
bool VideoDecoder::decode(const QByteArray &encoded)
{
AVPacket packet;
av_new_packet(&packet, encoded.size());
memcpy(packet.data, encoded.data(), encoded.size());
//TODO: use AVPacket directly instead of Packet?
//TODO: some decoders might in addition need other fields like flags&AV_PKT_FLAG_KEY
int ret = avcodec_decode_video2(d->codec_ctx, d->frame, &d->got_frame_ptr, &packet);
av_free_packet(&packet);
if ((ret < 0) || (!d->got_frame_ptr))
return false;
d->sws_ctx = sws_getCachedContext(d->sws_ctx
, d->codec_ctx->width, d->codec_ctx->height, d->codec_ctx->pix_fmt
, d->width, d->height, d->pix_fmt
, (d->width == d->codec_ctx->width && d->height == d->codec_ctx->height) ? SWS_POINT : SWS_BICUBIC
, NULL, NULL, NULL
);
int v_scale_result = sws_scale(
d->sws_ctx,
d->frame->data,
d->frame->linesize,
0,
d->codec_ctx->height,
d->picture.data,
d->picture.linesize
);
Q_UNUSED(v_scale_result);
if (d->frame->interlaced_frame)
avpicture_deinterlace(&d->picture, &d->picture, d->pix_fmt, d->width, d->height);
return true;
}
bool视频解码器::解码(常量QByteArray和编码)
{
数据包;
av_新_数据包(&packet,encoded.size());
memcpy(packet.data,encoded.data(),encoded.size());
//TODO:直接使用AVPacket而不是Packet?
//TODO:一些解码器可能还需要其他字段,如flags和AV_PKT_FLAG_KEY
int-ret=avcodec\u decode\u video2(d->codec\u ctx,d->frame,&d->got\u frame\u ptr,&packet);
av_免费_数据包(&数据包);
如果((ret<0)| |(!d->got_frame_ptr))
返回false;
d->sws\U ctx=sws\U getCachedContext(d->sws\U ctx
,d->codec_ctx->width,d->codec_ctx->height,d->codec_ctx->pix_fmt
,d->宽度,d->高度,d->pix\U fmt
,(d->width==d->codec\u ctx->width&&d->height==d->codec\u ctx->height)?SWS\u点:SWS\u双三次曲线
,空,空,空
);
int v_比例结果=sws_比例(
d->sws_ctx,
d->帧->数据,
d->框架->线条尺寸,
0,
d->codec_ctx->高度,
d->picture.data,
d->picture.linesize
);
Q_未使用(v_标度结果);
如果(d->帧->交错帧)
avpicture\u解交错(&d->picture,&d->picture,d->pix\U fmt,d->宽度,d->高度);
返回true;
}
谢谢Vibgyor,实际上发送方是spydroid开源软件,它的rtp头看起来不包含很多东西。。它由有效负载类型、序列号、时间戳、同步源标识符组成。。其中任何一个表示视频流信息??我不这么认为。。我仍在努力,并将更新我的进度。感谢拉尔夫,结果证明spydroid在单nal模式和fu-1模式下都发送rtp包,所以我想我需要将fu-1情况下的数据包作为rtp头处理,但不知道如何使用ffmpeg库解码rtp。我认为RTP层没有功能,这就是为什么我要从H264开始这项工作:(…我能得到一些建议吗?如果ffmpeg在RTP层不起作用,你要么在将代码传递给ffmpeg之前自己编写代码(没有那么糟糕),要么使用另一个第三方库。Live555(www.Live555.com)将是一个开源LGPL库,用于处理RTP,包括H.264负载特定的打包等。@Ralf我相信单NAL单元数据包模式也是RFC6184的一部分,有关RFC,请参阅第5.6节。我不确定您为什么说它不需要RTP头。如果我错了,请纠正我。@Krishna_Oza谢谢,没错,我没有表达得很好。更新答案。