将原始Genicam H.264数据读取到avlib [英] Read raw Genicam H.264 data to 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屋!