我尝试熟悉 libav,以便处理来自 GenICam 支持相机的原始 H.264 流。我想通过 GenICam 提供的接口 (API) 接收原始数据,然后将该数据转发到 libav 以生成一个容器文件,然后将其流式传输到 VLC 等播放设备或(稍后)到自己实现的展示。
到目前为止,我使用了 GenICam 示例代码,它将原始 H.264 数据传输到“sample.h264”文件中。这个文件,我已经通过命令行工具 ffmpeg,为了生成一个 mp4 容器文件,我可以在 VLC 中打开和观看
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 是什么意思?
下一个问题是,之后要做什么才能获得可以(实时)流式传输到播放器的容器?
在此先感谢,迈克