将原始Genicam H.264数据读取到avlib [英] Read raw Genicam H.264 data to avlib

查看:212
本文介绍了将原始Genicam H.264数据读取到avlib的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I try to get familiar with libav in order to process a raw H.264 stream from a GenICam supporting camera. 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示例代码,该示例代码将原始H.264数据传输到"sample.h264"文件中.我已经通过命令行工具ffmpeg放置了此文件,以便生成一个我可以在VLC中打开并观看的mp4容器文件

So far, I played around with the GenICam sample code, which transferres the raw H.264 data into a "sample.h264" file. 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

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

目前,我将深入研究每个H.264,ffmpeg,libav和视频处理的示例和文档.我必须承认,作为一个初学者,这让我很困惑. 我认为我已经找到了相应的libav函数,这些函数将对我的工作有所帮助:

Currently, I dig through examples and documentations for each H.264, ffmpeg, libav and video processing in general. 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:

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

I think, basically, I need the functions avcodec_send_packet() and avcodec_receive_packet() (since avcodec_decode_video2() is deprecated). Before that, I set up an avCodedContext structure and open (or combine?!?) it with the H.264 codec (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)
  ..
}

上面代码的结果是,对send_packet()和receive_frame()的调用均返回错误代码(-22和-11),但我无法通过av_strerror()对其进行解密(它只表示,这些是错误代码22和11).

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

也许作为那些想知道是否

Maybe as an additional information for those who wonder if

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

是有效操作... 首次调用此操作后,avPacket-> data的内容为

is a valid operation... After the very first call to this operation, the content of avPacket->data is

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

由于NAL标记和开头的数字,以某种方式看起来是可以预期的吗? 我不知道,因为我确实是个初学者....

which somehow looks as something to be expected becaus of the NAL marker and number in the beginning? I don't know, since I'm really a total beginner....

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

The question now is, am I on the right path? What is missing and what do the codes 22 and 11 mean?

下一个问题是,为了得到一个我可以(实时)流式传输到播放器的容器,该怎么办?

The next question would be, what to do afterwards, in order to get a container that I can stream (realtime) to a player?

预先感谢, 迈克

推荐答案

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

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);

我不得不手动填写"avCodecContext"和"avPacket"的一些参数:

I had to manually fill some parameters of 'avCodecContext' and '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接收的,可能不是该字段的适当参数,但至少我再也没有出现任何错误.

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.

因为这回答了我最初的问题,即我如何将原始数据获取到libav的结构中,所以我认为问题得到了解决.

Since this answers my initial question on how I get the raw data into the structures of libav, I think, the question is answered.

Vencat在推荐部分的讨论和建议引起了我的其他问题,但是我想应该在一个新问题中进行讨论.

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.

这篇关于将原始Genicam H.264数据读取到avlib的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆