将原始Genicam H.264数据读取到avlib

问题描述 投票:0回答:1

我尝试熟悉libav,以便从支持GenICam的相机处理原始H.264流。我希望通过GenICam提供的接口(API)接收原始数据,然后将该数据转发到libav中,以便生成一个容器文件,然后将其传输到像VLC这样的播放设备或(稍后)传输到自己实现的显示。

到目前为止,我使用了GenICam示例代码,它将原始H.264数据转换为“sample.h264”文件。这个文件,我已经通过命令行工具ffmpeg,以生成一个mp4容器文件,我可以打开并在VLC中观看

command: ffmpeg -i "sample.h264" -c:v copy -f mp4 "out.mp4"

目前,我通过挖掘每个H.264,ffmpeg,libav和视频处理的示例和文档。我不得不承认,作为初学者,它让我很困惑。我正处于这样的地步,我认为我找到了有助于我的事业的相应的libav功能:

我认为,基本上,我需要函数avcodec_send_packet()和avcodec_receive_packet()(因为不推荐使用avcodec_decode_video2())。在此之前,我设置了一个avCodedContext结构并用H.264编解码器(AV_CODEC_ID_H264)打开(或组合?!?)。

到目前为止,我的代码看起来像这样(省略错误检查和其他东西):

...
AVCodecContext* avCodecContext = nullptr;
AVCodec *avCodec = nullptr;
AVPacket *avPacket = av_packet_alloc();
AVFrame *avFrame = nullptr;
...
avCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
avCodecContext = avcodec_alloc_context3(avCodec);
avcodec_open2 ( avCodecContext, avCodec, NULL );
av_init_packet(avPacket);
...

while(receivingRawDataFromCamera)
{
  ...
  // receive raw data via GenICam
  DSGetBufferInfo<void*>(hDS, sBuffer.BufferHandle, BUFFER_INFO_BASE, NULL, pPtr)

  // libav action
  avPacket->data =static_cast<uint8_t*>(pPtr);  
  avErr = avcodec_send_packet(avCodecContext, avPacket);
  avFrame = av_frame_alloc();
  avErr = avcodec_receive_frame( avCodecContext, avFrame);

  // pack frame in container? (not implemented yet)
  ..
}

上面代码的结果是,对send_packet()和receive_frame()的调用都返回错误代码(-22和-11),我无法通过av_strerror()解密(它只是说,这些都是错误代码22和11)。

编辑:可能作为一个额外的信息,谁想知道是否

avPacket->data = static_cast<uint8_t*>(pPtr);

是一个有效的操作......在第一次调用此操作后,avPacket-> data的内容是

{0x0, 0x0, 0x0, 0x1, 0x67, 0x64, 0x0, 0x28, 0xad, 0x84, 0x5,
  0x45, 0x62, 0xb8, 0xac, 0x54, 0x74, 0x20, 0x2a, 0x2b, 0x15, 0xc5,
  0x62}

由于NAL标记和数字在一开始,某种程度上看起来像预期的东西?我不知道,因为我真的是一个初学者....

现在的问题是,我是在正确的道路上吗?缺少什么,代码22和11是什么意思?

接下来的问题是,为了获得一个我可以流式传输(实时)给玩家的容器,该怎么办呢?

提前谢谢,邮件

h.264 libav genicam
1个回答
0
投票

至少对于最初提出的问题,我找到了自己的解决方案:

为了摆脱调用函数的错误

avcodec_send_packet(avCodecContext, avPacket);
...
avcodec_receive_frame( avCodecContext, avFrame);

我不得不手动填充'avCodecContext'和'avPacket'的一些参数:

avCodecContext->bit_rate = 8000000;
avCodecContext->width = 1920;
avCodecContext->height = 1080;
avCodecContext->time_base.num = 1;
avCodecContext->time_base.den = 25;
...
avPacket->data = static_cast<uint8_t*>(pPtr);
avPacket->size = datasize;
avPacket->pts = frameid;

而'datasize'和'frameid'是通过GenICam接收的,可能不是这些字段的适当参数,但至少我不会再出现任何错误。

由于这回答了我关于如何将原始数据导入libav结构的初步问题,我认为,问题得到了回答。

Vencat在评论部分的讨论和建议引出了我的其他问题,但我想这应该在一个新问题中讨论。

© www.soinside.com 2019 - 2024. All rights reserved.