我正在尝试使用 LibAV 编写一个 C 程序,该程序从网络摄像头获取输入视频并将其保存为 H264 MP4 文件。我正在修改一个工作程序,用于保存来自网络摄像头的 .ppm 帧。我无法转换 AVPackets 以便可以写入它们,但具体来说,avformat_write_header() 失败,并显示消息
[mp4 @ 0050c000] Codec for stream 0 does not use global headers but container format requires global headers
[mp4 @ 0050c000] Could not find tag for codec none in stream #0, codec not currently supported in container
该调用显然返回错误 -22,但我找不到实际解释该错误代码的地方。当 avformat_write_header() 尝试写入 MP4 时,如何强制添加全局 header ?代码如下;其中一些改编自this question ,但我正在尝试将其从输入视频文件调整为网络摄像头。
int _tmain(int argc, _TCHAR* argv[])
{
AVInputFormat *inputFormat = NULL;
AVDictionary *inputDictionary= NULL;
AVFormatContext *inputFormatCtx = NULL;
AVFormatContext *outputFormatCtx = NULL;
AVCodecContext *inputCodecCtxOrig = NULL;
AVCodecContext *inputCodecCtx = NULL;
AVCodecContext *outputCodecCtx;
AVCodec *inputCodec = NULL;
AVCodec *outputCodec = NULL;
AVStream *stream = NULL;
AVIOContext *avioContext = NULL;
avcodec_register_all();
av_register_all();
avdevice_register_all();
av_dict_set(&inputDictionary, "Logitech HD Pro Webcam C920", "video", 0);
avformat_alloc_output_context2(&outputFormatCtx, NULL, NULL, "output.mp4");
avio_open(&avioContext, "output.mp4", AVIO_FLAG_WRITE);
outputFormatCtx->pb = avioContext;
stream = avformat_new_stream(outputFormatCtx, outputCodec);
inputFormat = av_find_input_format("dshow");
int r = avformat_open_input(&inputFormatCtx, "video=Logitech HD Pro Webcam C920", inputFormat, &inputDictionary);
if (r != 0) {
fprintf(stderr, "avformat_open_input() failed with error %d!\n", r);
return -1; }
r = avformat_find_stream_info(inputFormatCtx, NULL);
if (r != 0) {
fprintf(stderr, "avformat_find_stream_info() failed!\n");
return -1; }
av_dump_format(inputFormatCtx, 0, "video=Logitech HD Pro Webcam C920", 0);
unsigned int i;
int videoStream;
videoStream = -1;
for (i = 0; i < inputFormatCtx->nb_streams; i++) {
if (inputFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO {
videoStream = i;
break; }
}
if (videoStream == -1)
{ return -1; }
inputCodecCtxOrig = inputFormatCtx->streams[videoStream]->codec;
inputCodec = avcodec_find_decoder(inputCodecCtxOrig->codec_id);
if (inputCodec == NULL) {
fprintf(stderr, "avcodec_find_decoder() failed!\n");
return -1; }
else { printf("Supported codec!\n"); }
inputCodecCtx = avcodec_alloc_context3(inputCodec);
if (inputCodecCtx == NULL) {
fprintf(stderr, "avcodec_alloc_context3() failed!\n");
return -1; }
if (avcodec_copy_context(inputCodecCtx, inputCodecCtxOrig) != 0) {
fprintf(stderr, "avcodec_copy_context() failed!\n");
return -1; }
if (avcodec_open2(inputCodecCtx,inputCodec,&inputDictionary) < 0) {
fprintf(stderr, "avcodec_open2() failed!\n");
return -1; }
outputFormatCtx->oformat = av_guess_format(NULL, "output.mp4", NULL);
outputFormatCtx->oformat->flags |= AVFMT_GLOBALHEADER;
outputCodecCtx = avcodec_alloc_context3(outputCodec);
avcodec_copy_context(outputCodecCtx, inputCodecCtx);
outputCodec = inputCodec;
avcodec_open2(outputCodecCtx, outputCodec, NULL);
AVPacket packet;
printf("foo\n");
int errnum = avformat_write_header(outputFormatCtx, &inputDictionary);
printf("bar %d\n", errnum);
while(av_read_frame(inputFormatCtx, &packet)>=0) {
av_interleaved_write_frame(outputFormatCtx, &packet);
av_free_packet(&packet);
}
avcodec_close(inputCodecCtx);
avcodec_close(inputCodecCtxOrig);
avformat_close_input(&inputFormatCtx);
return 0;
}
最佳答案
How can I force avformat_write_header() to add in global headers
全局 header 由编码器写入,稍后复用器从编解码器的 extra_data 字段中读取它们。因此,您应该在调用 avcodec_open2() 之前在编解码器的上下文中设置此标志。
outputCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
[mp4 @ 0050c000] Could not find tag for codec none in stream #0, codec not currently supported in container
您可以尝试显式设置编码器(即手动),或从原始输入 codeccontext 复制 codeccontext。
outputCodec = av_codec_find_encoder(AV_CODEC_ID_H264);
if(!outputCodec) return -1; //no encoder found
outputCodecCtx = avcodec_alloc_context3(outputCodec);
avcodec_copy_context(outputCodecCtx, inputCodecCtxOrig); //copy from orig
//You have to make sure each field is populated correctly
//with debugger or assertations
assert(outputCodecCtx->codec_id == AV_CODEC_ID_H264); //etc
outputCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
if(avcodec_open2(outputCodecCtx, outputCodec, NULL) <0) return -1;
关于c - 强制 LibAV 中的全局 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31272885/