简体   繁体   English

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

[英]Read raw Genicam H.264 data to avlib

I try to get familiar with libav in order to process a raw H.264 stream from a GenICam supporting camera. 我尝试熟悉libav,以便从支持GenICam的相机处理原始H.264流。 I'd like to receive the raw data via the GenICam provided interfaces (API), and then forward that data into libav in order to produce a container file that then is streamed to a playing device like VLC or (later) to an own implemented display. 我希望通过GenICam提供的接口(API)接收原始数据,然后将这些数据转发到libav中,以便生成一个容器文件,然后将其传输到像VLC这样的播放设备或(稍后)传输给自己实现的显示。

So far, I played around with the GenICam sample code, which transferres the raw H.264 data into a "sample.h264" file. 到目前为止,我使用了GenICam示例代码,它将原始H.264数据转换为“sample.h264”文件。 This file, I have put through the command line tool ffmpeg, in order to produce an mp4 container file that I can open and watch in VLC 这个文件,我已经通过命令行工具ffmpeg,以生成一个mp4容器文件,我可以打开并在VLC中观看

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

Currently, I dig through examples and documentations for each H.264, ffmpeg, libav and video processing in general. 目前,我通过挖掘每个H.264,ffmpeg,libav和视频处理的示例和文档。 I have to admit, as total beginner, it confuses me a lot. 我不得不承认,作为初学者,它让我很困惑。 I'm at the point where I think I have found the according libav functions that would help my undertaking: 我正处于这样的地步,我认为我找到了有助于我的事业的相应的libav功能:

I think, basically, I need the functions avcodec_send_packet() and avcodec_receive_packet() (since avcodec_decode_video2() is deprecated). 我认为,基本上,我需要函数avcodec_send_packet()和avcodec_receive_packet()(因为不推荐使用avcodec_decode_video2())。 Before that, I set up an avCodedContext structure and open (or combine?!?) it with the H.264 codec (AV_CODEC_ID_H264). 在此之前,我设置了一个avCodedContext结构并用H.264编解码器(AV_CODEC_ID_H264)打开(或组合?!?)。

So far, my code looks like this (omitting error checking and other stuff): 到目前为止,我的代码看起来像这样(省略错误检查和其他东西):

...
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)
  ..
}

The result of the code above is, that both calls to send_packet() and receive_frame() return error codes (-22 and -11), which I'm not able to decrypt via av_strerror() (it only says, these are error codes 22 and 11). 上面代码的结果是,对send_packet()和receive_frame()的调用都返回错误代码(-22和-11),我无法通过av_strerror()解密(它只是说,这些都是错误代码22和11)。

Edit: Maybe as an additional information for those who wonder if 编辑:可能作为一个额外的信息,谁想知道是否

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

is a valid operation... After the very first call to this operation, the content of avPacket->data is 是一个有效的操作......在第一次调用此操作后,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}

which somehow looks as something to be expected becaus of the NAL marker and number in the beginning? 由于NAL标记和数字在一开始,某种程度上看起来像预期的东西? I don't know, since I'm really a total beginner.... 我不知道,因为我真的是一个初学者....

The question now is, am I on the right path? 现在的问题是,我是在正确的道路上吗? What is missing and what do the codes 22 and 11 mean? 缺少什么,代码22和11是什么意思?

The next question would be, what to do afterwards, in order to get a container that I can stream (realtime) to a player? 接下来的问题是,为了获得一个我可以流式传输(实时)给玩家的容器,该怎么办呢?

Thanks in advance, Maik 迈克,提前谢谢

At least for the initally asked question I found the solution for myself: 至少对于最初提出的问题,我找到了自己的解决方案:

In order to get rid of the errors on calling the functions 为了摆脱调用函数的错误

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

I had to manually fill some parameters of 'avCodecContext' and 'avPacket': 我不得不手动填充'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;

whereas 'datasize' and 'frameid' are received via GenICam, and may not be the appropriate parameters for the fields, but at least I do not get any errors anymore. 而'datasize'和'frameid'是通过GenICam接收的,可能不是这些字段的适当参数,但至少我不会再出现任何错误。

Since this answers my initial question on how I get the raw data into the structures of libav, I think, the question is answered. 由于这回答了我关于如何将原始数据导入libav结构的初步问题,我认为,问题得到了回答。

The discussion and suggestions with/from Vencat in the commenst section lead to additional questions I have, but which should be discussed in a new question, I guess. 在Comcomst部分与Vencat的讨论和建议引发了我的其他问题,但我想这应该在一个新问题中讨论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM