mux / remux / box in memory h264 frames to mp4 via C / C++ (no ffmpeg cmdline)

0

I have looked at various tutorials and I am still struggling to correctly frame raw h264 into an mp4 container. The problem is the stream does not have an end (live) and is in memory, a lot of the examples available of muxers assume the streams are located on disk as files.

I have tried and looked at http://www.ffmpeg.org/doxygen/trunk/doc_2examples_2remuxing_8c-example.html
https://ffmpeg.org/doxygen/trunk/muxing_8c-source.html
and countless other examples.

This is what I have now:

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);

I get an infinite loop on read_packet after calling av_read_frame, I tried to construct the packets myself by also doing

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);
}

But this does not work either. Some help would be greatly appreciated or guidance where to look (perhaps drop libFFMPEG and look elsewhere, etc).

VLC errors look like:

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]

or

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)
ffmpeg
mp4
h.264
asked on Stack Overflow Feb 28, 2019 by Vans S

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0