我试图熟悉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的含义是什么?
下一个问题是,为了得到一个可以(实时)传输给播放器的容器,之后该怎么做?
提前谢谢,Maik
发布于 2019-04-18 17:46:21
至少对于最初提出的问题,我自己找到了解决方案:
为了消除调用函数时的错误
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的讨论和建议导致了我还有其他问题,但我想这些问题应该在新问题中讨论。
https://stackoverflow.com/questions/55705419
复制相似问题