我试图熟悉libav,以便处理来自支持GenICam的摄像机的原始H.264流。 我想通过GenICam提供的接口(API)接收原始数据,然后将这些数据转发到libav中,以生成一个容器文件,然后将其流式传输到VLC等播放设备,或者(后来)流式传输到自己实现的显示。
到目前为止,我试用了GenICam示例代码,该示例代码将原始H.264数据传输到“ sample.h264”文件中。我已经通过命令行工具ffmpeg放置了此文件,以便生成一个我可以在VLC中打开并观看的mp4容器文件
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的含义是什么?
下一个问题是,为了获得一个我可以(实时)流式传输到播放器的容器,该怎么办?
预先感谢, 迈克
答案 0 :(得分: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在推荐部分的讨论和建议引起了我的其他问题,但是我想应该在一个新问题中进行讨论。