Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Compression Techniques How can I pack raw H264 stream to MKV format?

  • How can I pack raw H264 stream to MKV format?

    Posted by Howz Smith on October 9, 2011 at 8:57 am

    Hi all,
    I want to pack the H264 stream from hardware encoder to mkv format, however, the output file “test.mkv” can’t be played by video player. The following is my codes. Can someone help me find the reason? By the way, if I use “test.avi” as the output filename, the avi file can be create successfully.

    Thanks.

    ===========Codes====================
    static AVOutputFormat *outfmt;
    static AVFormatContext *outcxt;
    static AVStream *video_st;
    static AVPacket pkt;

    #define OUTFILENAME “test.mkv”
    char *ofilename;

    static AVStream * add_video_stream(AVFormatContext *oc, enum CodecID codec_id)
    {
    AVStream *st;
    AVCodecContext *c;
    st = av_new_stream(outcxt, 0);
    if(!st)
    {
    printf(“Fail to allocate output video stream.n”);
    return NULL;
    }

    c = st->codec;
    c->codec_id = codec_id;
    c->codec_type = AVMEDIA_TYPE_VIDEO;

    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 352;
    c->height = 288;
    /* time base: this is the fundamental unit of time (in seconds) in terms
    of which frame timestamps are represented. for fixed-fps content,
    timebase should be 1/framerate and timestamp increments should be
    identically 1. */
    c->time_base.den = 6;
    c->time_base.num = 1;
    c->gop_size = 12; /* emit one intra frame every twelve frames at most */
    c->pix_fmt = PIX_FMT_YUV420P;
    // some formats want stream headers to be separate
    if(oc->oformat->flags & AVFMT_GLOBALHEADER)
    c->flags |= CODEC_FLAG_GLOBAL_HEADER;

    return st;

    }

    static void open_video(AVFormatContext *oc, AVStream *st)
    {
    AVCodec *codec;
    AVCodecContext *c;

    c = st->codec;
    if(CODEC_ID_H264 == c->codec_id)
    {
    fprintf(stderr, “codec H264n”);
    }

    /* find the video decoder */
    codec = avcodec_find_decoder(c->codec_id);
    if (!codec) {
    fprintf(stderr, “codec not found %dn”, c->codec_id);
    exit(1);
    }

    /* open the codec */
    if (avcodec_open(c, codec) < 0) {
    fprintf(stderr, “could not open codecn”);
    exit(1);
    }
    }

    int MkvInit(void)
    {
    av_register_all();
    avcodec_init();
    ofilename = OUTFILENAME;

    /*guess foramt*/
    outfmt = av_guess_format(NULL,ofilename,NULL);
    if(!outfmt)
    {
    printf(“Could not deduce output format from file extension: using mkv.n”);
    return -1;
    }

    if (!outfmt)
    {
    printf(“Could not find suitable output formatn”);
    return -1;
    }

    outcxt = avformat_alloc_context();
    if(!outcxt)
    {
    fprintf(stderr, “Memory error outcxtn”);
    return -1;
    }

    outcxt->oformat = outfmt;
    snprintf(outcxt->filename, sizeof(outcxt->filename), “%s”, ofilename);
    outcxt->oformat->video_codec = CODEC_ID_H264;

    video_st = NULL;
    video_st = add_video_stream(outcxt, CODEC_ID_H264);

    if (av_set_parameters(outcxt, NULL) < 0)
    {
    fprintf(stderr, “Invalid output format parametersn”);
    return -1;
    }

    dump_format(outcxt, 0, ofilename,1);
    open_video(outcxt, video_st);

    if(!(outcxt->flags & AVFMT_NOFILE))
    {
    if(url_fopen(&outcxt->pb, ofilename, URL_WRONLY) < 0)
    {
    printf(“Fail to open the output file %sn”, ofilename);
    exit(1);
    }
    }

    if(av_write_header(outcxt) < 0)
    {
    fprintf(stderr, “Fail to write the header of output file.n”);
    exit(1);
    }

    dump_format(outcxt, 0, ofilename,1);
    return 0;
    }

    int MkvWriteBuffer(int isKeyFrame, char *buffer, int buffer_len)
    {
    int ret;
    av_init_packet(&pkt);

    pkt.pts = AV_NOPTS_VALUE;
    pkt.dts = AV_NOPTS_VALUE;
    pkt.convergence_duration = AV_NOPTS_VALUE;

    if(isKeyFrame)
    {
    pkt.flags |= PKT_FLAG_KEY;
    }

    pkt.data = buffer;
    pkt.size = buffer_len;
    pkt.stream_index= video_st->index;

    ret = av_interleaved_write_frame(outcxt, &pkt);

    if(ret != 0)
    {
    printf(“write frame errorn”);
    return -1;
    }

    printf(“write frame %dn”, buffer_len);
    return 0;
    }

    int MkvStop()
    {
    printf(“start av_free_packetn”);
    av_free_packet(&pkt);
    printf(“start av_write_trailern”);
    av_write_trailer(outcxt);
    printf(“start avcodec_closen”);
    avcodec_close(video_st->codec);
    printf(“start av_freep codecn”);
    av_freep(&outcxt->streams[0]->codec);
    printf(“start av_freep streamsn”);
    av_freep(&outcxt->streams[0]);
    if (!(outfmt->flags & AVFMT_NOFILE))
    {
    printf(“start url_fclose streamsn”);
    /* close the output file */
    url_fclose(outcxt->pb);

    }

    printf(“start av_free outcxtn”);
    av_free(outcxt);
    return 0;
    }

    Igsgk Igsgk replied 14 years, 2 months ago 2 Members · 1 Reply
  • 1 Reply
  • Igsgk Igsgk

    June 15, 2012 at 11:34 am

    Hi Howz,

    I used your codes to make avi and mkv file and both files work!!.

    Sinan

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy