我看过各种教程,但仍在努力将原始h264正确地放入mp4容器中。问题在于流没有结束(活动)并且在内存中,许多复用器的可用示例都假定流作为文件位于磁盘上。
我已经尝试并看过
http://www.ffmpeg.org/doxygen/trunk/doc_2examples_2remuxing_8c-example.html
https://ffmpeg.org/doxygen/trunk/muxing_8c-source.html
还有无数其他示例。
这就是我现在拥有的:
AVFormatContext *outFmtCtx = NULL;
AVFormatContext *inFmtCtx = NULL;
std::vector<uint8_t> g_p;
static int read_packet(void *opaque, uint8_t *pBuf, int nBuf) {
printf("read_packet %d\n", g_p.size());
memcpy(pBuf, &g_p[0], g_p.size());
return g_p.size();
}
static int write_packet(void *opaque, uint8_t *buf, int buf_size) {
printf("write_packet %d %lld\n", buf_size, timestamp_micro());
return buf_size;
}
static int64_t seek_packet(void *opaque, int64_t offset, int whence) {
printf("seek_packet\n");
exit(0);
return 0;
}
void create_mp4() {
av_log_set_level(AV_LOG_DEBUG);
//alloc memory buffer
uint8_t *avioc_buffer = NULL;
int avioc_buffer_size = 8 * 1024 * 1024;
avioc_buffer = (uint8_t *)av_malloc(avioc_buffer_size);
if (!avioc_buffer) {
printf("failed make avio buffer\n");
exit(1);
}
AVIOContext* pIOCtx = avio_alloc_context(avioc_buffer, avioc_buffer_size, 1,
NULL/*outptr*/, &read_packet, &write_packet, &seek_packet);
if (!pIOCtx) {
printf("failed make avio context\n");
exit(1);
}
inFmtCtx = avformat_alloc_context();
inFmtCtx->pb = pIOCtx;
inFmtCtx->iformat = av_find_input_format("h264");
avformat_open_input(&inFmtCtx, "", inFmtCtx->iformat, NULL);
AVOutputFormat* outFmt = av_guess_format("mp4", NULL, NULL);
avformat_alloc_output_context2(&outFmtCtx, outFmt, NULL, NULL);
//set the AIO buffer to the memory one
outFmtCtx->pb = pIOCtx;
//outFmtCtx->flags = AVFMT_FLAG_CUSTOM_IO;//pIOCtx;
AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
AVStream * outStrm = avformat_new_stream(outFmtCtx, codec);
avcodec_get_context_defaults3(outStrm->codec, codec);
outStrm->id = 0;
outStrm->codec->coder_type = AVMEDIA_TYPE_VIDEO;
outStrm->codec->codec_id = AV_CODEC_ID_H264;
outStrm->codec->bit_rate = 8000000;
outStrm->codec->width = 1280;
outStrm->codec->height = 720;
outStrm->codec->time_base.den = 60;
outStrm->codec->time_base.num = 1;
outStrm->codec->gop_size = 0xffffffff;
outStrm->codec->pix_fmt = AV_PIX_FMT_NV12;
outStrm->duration = 0;
//Allow it to play immediately
AVDictionary* options = nullptr;
av_dict_set( &options, "movflags", "empty_moov+default_base_moof+frag_keyframe", 0 );
avformat_write_header(outFmtCtx, &options);
printf("mp4 muxer created\n");
}
//set the first raw h264 frame from capture
g_p = raw_h264_frame;
AVPacket pkt;
//call av_read_frame (infinite loop here on read_packet)
int wret = av_read_frame(inFmtCtx, &pkt);
调用av_read_frame后,我在read_packet上遇到了无限循环,我也尝试自己构造数据包
AVPacket pkt;
av_init_packet(&pkt);
if (nFrame == 0) {
pkt.flags |= AV_PKT_FLAG_KEY;
}
pkt.stream_index = 0;
pkt.data = &raw_h264_frame[0];
pkt.size = raw_h264_frame.size();
//pkt.dts = AV_NOPTS_VALUE;
//pkt.pts = AV_NOPTS_VALUE;
pkt.dts = nFrame;
pkt.pts = nFrame;
int ret = av_interleaved_write_frame(outFmtCtx, &pkt);
if (ret < 0) {
printf("error av_write_frame\n");
exit(1);
}
但这也不起作用。我们将不胜感激某些帮助,或提供指导以指导您查找位置(也许删除libFFMPEG并在其他位置查找,等等)。
VLC错误如下:
mp4 warning: out of bound child �
mp4 warning: out of bound child �
mp4 warning: no chunk defined
mp4 warning: STTS table of 0 entries
mp4 warning: cannot select track[Id 0x1]
或
mp4 warning: no chunk defined
mp4 warning: STTS table of 0 entries
mp4: Fragment sequence discontinuity detected 1 != 0
avcodec warning: thread type 1: disabling hardware acceleration
main warning: picture is too late to be displayed (missing 14 ms)
main warning: picture is too late to be displayed (missing 14 ms)
main warning: picture is too late to be displayed (missing 14 ms)