多路复用器/ remux /盒中的内存h264帧通过C / C ++转换为mp4(无ffmpeg cmdline)

时间:2019-02-28 18:08:47

标签: ffmpeg mp4 h.264

我看过各种教程,但仍在努力将原始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)

0 个答案:

没有答案