我在这里指的是这个线程: Muxing AVPackets into mp4 file
那里的问题基本上与我相同,第一个答案看起来非常有希望。 用户 pogorskiy 提供的源代码(伪类)似乎完全符合我的要求:
AVOutputFormat * outFmt = av_guess_format("mp4", NULL, NULL);
AVFormatContext *outFmtCtx = NULL;
avformat_alloc_output_context2(&outFmtCtx, outFmt, NULL, NULL);
AVStream * outStrm = av_new_stream(outFmtCtx, 0);
AVCodec * codec = NULL;
avcodec_get_context_defaults3(outStrm->codec, codec);
outStrm->codec->coder_type = AVMEDIA_TYPE_VIDEO;
///....
/// set some required value, such as
/// outStrm->codec->flags
/// outStrm->codec->sample_aspect_ratio
/// outStrm->disposition
/// outStrm->codec->codec_tag
/// outStrm->codec->bits_per_raw_sample
/// outStrm->codec->chroma_sample_location
/// outStrm->codec->codec_id
/// outStrm->codec->codec_tag
/// outStrm->codec->time_base
/// outStrm->codec->extradata
/// outStrm->codec->extradata_size
/// outStrm->codec->pix_fmt
/// outStrm->codec->width
/// outStrm->codec->height
/// outStrm->codec->sample_aspect_ratio
/// see ffmpeg.c for details
avio_open(&outFmtCtx->pb, outputFileName, AVIO_FLAG_WRITE);
avformat_write_header(outFmtCtx, NULL);
for (...)
{
av_write_frame(outFmtCtx, &pkt);
}
av_write_trailer(outFmtCtx);
avio_close(outFmtCtx->pb);
avformat_free_context(outFmtCtx);
pkt 数据,我是从connectec摄像机的第三方API收到的。没有可打开的文件可从中读取输入数据,也没有可从相机接收的RTSP流。这只是一个API调用,它为我提供了指向H264编码帧的指针,该帧正是AVPacket的原始数据。
无论如何,我尝试将这段代码用作应用程序的基础,但是出现的第一个问题是,我遇到运行时错误:
Could not find tag for codec none in stream #0, codec not currently supported in container
因此,我开始按照 pogorskiy 的建议向编解码器添加更多信息:
outStrm->codec->codec_id = AV_CODEC_ID_H264;
outStrm->codec->width = 1920;
outStrm->codec->height = 1080;
现在,我希望提供一个codec_id,运行时消息至少会有所不同,但是仍然相同:
Could not find tag for codec none in stream #0, codec not currently supported in container
关于如何设置结构以便打开mp4文件以将数据包写入的任何想法吗?
答案 0 :(得分:1)
好的,我知道了。至少我可以打开一个mp4文件,并将H264编码的数据包写入其中。该文件甚至在VLC中打开并显示第一帧。仅此而已,只是一个开始。
所以我将代码放在她身上,以显示此最小解决方案。如果有人提出他/她的意见,我仍然感到非常高兴,因为它仍然无法完美运行...
char outputFileName[] = "camera.mp4";
av_log_set_level(AV_LOG_DEBUG);
AVOutputFormat * outFmt = av_guess_format("mp4", NULL, NULL);
AVFormatContext *outFmtCtx = NULL;
avformat_alloc_output_context2(&outFmtCtx, outFmt, NULL, NULL);
AVStream * outStrm = avformat_new_stream(outFmtCtx, NULL);
outStrm->id = 0;
outStrm->time_base = {1, 30};
outStrm->avg_frame_rate = {1, 30};
AVCodec * codec = NULL;
avcodec_get_context_defaults3(outStrm->codec, codec);
outFmtCtx->video_codec_id = AV_CODEC_ID_H264;
///....
/// set some required value, such as
/// outStrm->codec->flags
/// outStrm->codec->sample_aspect_ratio
/// outStrm->disposition
/// outStrm->codec->codec_tag
/// outStrm->codec->bits_per_raw_sample
/// outStrm->codec->chroma_sample_location
outStrm->codecpar->codec_id = AV_CODEC_ID_H264;
outStrm->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
/// outStrm->codec->time_base
/// outStrm->codec->extradata
/// outStrm->codec->extradata_size
/// outStrm->codec->pix_fmt
outStrm->codecpar->width = 1920;
outStrm->codecpar->height = 1080;
/// outStrm->codec->sample_aspect_ratio
/// see ffmpeg.c for details
avio_open(&outFmtCtx->pb, outputFileName, AVIO_FLAG_WRITE);
avformat_write_header(outFmtCtx, NULL);
*** Camera access loop via GenICam API starts here ***
n++;
av_init_packet(&avPacket);
avPacket.data = static_cast<uint8_t*>(pPtr); // raw data from the Camera with H264 encoded frame
avPacket.size = datasize; // datasize received from the GenICam API along with pPtr (the raw data)
avPacket.pts = (1/30) * n; // stupid try to set pts and dts somehow... Working on this...
avPacket.dts = (1/30) * (n-1);
avPacket.pos = n;
avPacket.stream_index = outStrm->index;
av_write_frame(outFmtCtx, &avPacket);
**** Camera access loop ends here ****
av_write_trailer(outFmtCtx);
avio_close(outFmtCtx->pb);
avformat_free_context(outFmtCtx);
正如我所说,生成的mp4文件在瞬间显示了第一帧,此后停止播放。 我认为会显示第一帧,因为我确保这是一个包含完整图像的I帧。
我不知道是否必须向muxer提供一些其他数据才能获得可用的mp4文件。我还在努力。
任何评论和想法都非常欢迎!
谢谢, 迈克