[Libav-user] Generated H264 video is only 1 second long with only 1 frame shown (Probably a PTS/DTS problem)

M N assemblerx86 at yandex.com
Wed Sep 21 23:23:14 EEST 2016


Hi,

 After encoding an H264 video, the output video has 1 frame only shown with duration of 1 second (That's using VLC media player, it doesn't even play with WMP - Shows corrupt file -), I also get "[libx264 @ 01f60060] non-strictly-monotonic PTS" Warning while encoding frames, so I guess it is a PTS problem. How do I set the PTS/DTS for a packet in H264?

Here is my code: (http://pastebin.com/WibnmKLV)
********************************************
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
#include "libavutil/rational.h"

#include <stdio.h>

int main()
{
    av_register_all();
    //avcodec_register_all();

    av_log_set_level(AV_LOG_DEBUG);


    AVFormatContext *ps = avformat_alloc_context();

    AVFormatContext *ps2 = NULL;//avformat_alloc_context();
    AVOutputFormat *oF = av_guess_format("mp4", NULL, "video/mp4");


    if(avformat_open_input(&ps, "vid.mp4", NULL, NULL) != 0)
    {
        printf("Failed to open input file.\n");
        return -1;
    }

    avformat_alloc_output_context2(&ps2, oF, NULL, "vid2.mp4");

    avformat_find_stream_info(ps, NULL);

    ps2->metadata = ps->metadata;

    AVCodecContext **pC = (AVCodecContext**)malloc(ps->nb_streams), **p2C = (AVCodecContext**)malloc(ps->nb_streams);

    AVStream *oStream = NULL;
    AVStream *iStream = NULL;

    AVCodec *encoder = NULL;
    AVCodec *decoder = NULL;
    AVCodecContext *strCtx = NULL;

    unsigned int i;

    avio_open(&ps2->pb, "vid2.mp4", AVIO_FLAG_WRITE);

    for(i = 0; i < ps->nb_streams; i++)
    {
        printf("%d\n", i);

        iStream = ps->streams[i];

        pC[i] = iStream->codec;


        if(pC[i]->codec_type == AVMEDIA_TYPE_UNKNOWN)
        {
            printf("Skipping bad stream\n");
            continue;
        }

        if(pC[i]->codec_type == AVMEDIA_TYPE_VIDEO || pC[i]->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            encoder = avcodec_find_encoder(pC[i]->codec_id);
            //encoder->init(p2C[i]);
            if (!encoder)
            {
                av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n");
                return AVERROR_INVALIDDATA;
            }

            oStream = avformat_new_stream(ps2, encoder);

            strCtx = oStream->codec; //We have to set oStream->codec parameters for write_header to work,
                                    //since write_header only relies on the stream parameters.


            p2C[i] = avcodec_alloc_context3(encoder);


            AVDictionary *param = NULL;

            if (pC[i]->codec_type == AVMEDIA_TYPE_VIDEO)
            {
                p2C[i]->width = pC[i]->width;
                p2C[i]->height = pC[i]->height;

                if (encoder->pix_fmts)
                    p2C[i]->pix_fmt = encoder->pix_fmts[0];
                else
                    p2C[i]->pix_fmt = pC[i]->pix_fmt;

                p2C[i]->sample_rate = pC[i]->sample_rate;
                p2C[i]->sample_aspect_ratio = pC[i]->sample_aspect_ratio;
                p2C[i]->frame_size = pC[i]->frame_size;
                p2C[i]->time_base = pC[i]->time_base;

                strCtx->width = pC[i]->width;
                strCtx->height = pC[i]->height;

                if (encoder->pix_fmts)
                    strCtx->pix_fmt = encoder->pix_fmts[0];
                else
                    strCtx->pix_fmt = pC[i]->pix_fmt;
                strCtx->sample_rate = pC[i]->sample_rate;
                strCtx->sample_aspect_ratio = pC[i]->sample_aspect_ratio;
                strCtx->time_base = pC[i]->time_base;
                strCtx->frame_size = pC[i]->frame_size;

            }
            else
            {
                p2C[i]->sample_rate = pC[i]->sample_rate;
                p2C[i]->channel_layout = pC[i]->channel_layout;
                p2C[i]->channels = av_get_channel_layout_nb_channels(p2C[i]->channel_layout);
                // take first format from list of supported formats
                p2C[i]->sample_fmt = encoder->sample_fmts[0];
                p2C[i]->time_base = (AVRational){1, p2C[i]->sample_rate};

                strCtx->sample_rate = pC[i]->sample_rate;
                strCtx->channel_layout = pC[i]->channel_layout;
                strCtx->channels = av_get_channel_layout_nb_channels(strCtx->channel_layout);
                // take first format from list of supported formats
                strCtx->sample_fmt = encoder->sample_fmts[0];
                strCtx->time_base = (AVRational){1, strCtx->sample_rate};
            }

            //AVCodecParameters *par = avcodec_parameters_alloc();
            //avcodec_parameters_from_context(par, pC[i]);
            //avcodec_parameters_to_context(p2C[i], par);

            decoder = avcodec_find_decoder(pC[i]->codec_id);
            if(decoder == NULL) printf("Couldn't find decoder\n");

            if(pC[i]->codec_type == AVMEDIA_TYPE_VIDEO)
            {
                int ret1 = avcodec_open2(pC[i], decoder, &param);
                int ret2 = avcodec_open2(p2C[i], encoder, &param);
                char err[200];
                av_make_error_string(err, 200, ret2);
                printf("Ret2 %d: %s\n", ret2, err);
            }
            else
            {
                int ret1 = avcodec_open2(pC[i], decoder, NULL);
                int ret2 = avcodec_open2(p2C[i], encoder, NULL);
                printf("Ret1: %d | Ret2: %d\n", ret1, ret2);
            }

            //p2C-> = pC[i]->pts;
        }
        else if (pC[i]->codec_type == AVMEDIA_TYPE_UNKNOWN) {
            av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);
            //return AVERROR_INVALIDDATA;
        }
        else
        {
            //avcodec_copy_context(oStream->codec, iStream->codec);
            printf("BUG\n");
        }
    }
    printf("done\n");

    int ret = avformat_write_header(ps2, NULL);
    char err[200];
    av_make_error_string(err, 200, ret);
    printf("Write header %d: %s\n", ret, err);

    unsigned int j = 0;
    for(;; ++j)
    {
        AVPacket *pkts = av_packet_alloc();
        pkts->data = NULL;
        pkts->size = 0;
        AVPacket *pktr = av_packet_alloc();
        pktr->data = NULL;
        pktr->size = 0;
        AVFrame *rawFrame = av_frame_alloc();
        av_init_packet(pkts);
        av_init_packet(pktr);
        if(av_read_frame(ps, pkts) != 0) break;

        //pkts->pts = av_rescale_q_rnd(pkts->pts, ps->streams[pkts->stream_index]->time_base, ps2->streams[pkts->stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
        //pkts->dts = av_rescale_q_rnd(pkts->dts, ps->streams[pkts->stream_index]->time_base, ps2->streams[pkts->stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
        //pkts->duration = av_rescale_q(pkts->duration, ps->streams[pkts->stream_index]->time_base, ps->streams[pkts->stream_index]->time_base);

        //pktr->pts = av_rescale_q_rnd(pkts->pts, ps->streams[pkts->stream_index]->time_base, ps2->streams[pkts->stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
        //pktr->dts = av_rescale_q_rnd(pkts->dts, ps->streams[pkts->stream_index]->time_base, ps2->streams[pkts->stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
        //pktr->duration = av_rescale_q(pkts->duration, ps->streams[pkts->stream_index]->time_base, ps->streams[pkts->stream_index]->time_base);
        //decoding
        pktr->stream_index = pkts->stream_index;


        //decoding
        int dret = 0, eret = 0;
        dret = avcodec_send_packet(pC[pkts->stream_index], pkts);
        if(dret == 0)
        {
            if(avcodec_receive_frame(pC[pkts->stream_index], rawFrame) == 0)
            {

                //rawFrame->pts = av_frame_get_best_effort_timestamp(rawFrame);
                //encoding
                eret = avcodec_send_frame(p2C[pktr->stream_index], rawFrame);
                if(eret == 0)
                {
                    if(avcodec_receive_packet(p2C[pktr->stream_index], pktr) == 0)
                    {
                        printf("Succ dec/enc Stream index %d\n", pkts->stream_index);
                        if(av_interleaved_write_frame(ps2, pktr) != 0)
                        {
                            printf("Failed to write packet\n");
                            break;
                        }
                        //printf("packet written\n");
                    } else printf("avcodec_receive_packet\n");
                }
                else if(eret == AVERROR(EINVAL))
                {
                    avcodec_flush_buffers(p2C[i]);
                }
                else if(eret == AVERROR(EAGAIN))
                {
                    printf("avcodec_send_frame requires flushing...\n");
                    avcodec_send_frame(p2C[pkts->stream_index], NULL);
                    while(1)
                    {
                        eret = avcodec_receive_packet(p2C[pktr->stream_index], pktr);
                        if(eret != AVERROR_EOF) break;
                        printf("eret: %d\n", eret);
                    }
                    //avcodec_flush_buffers(pC[pkts->stream_index]);
                }
                else
                {
                    printf("avcodec_send_frame Stream index %d\n", pkts->stream_index);
                }
            } else printf("avcodec_receive_frame\n");
        }
        else if(dret == AVERROR(EINVAL))
        {
            avcodec_flush_buffers(pC[i]);
        }
        else if(dret == AVERROR(EAGAIN))
        {
            printf("avcodec_send_packet requires flushing...\n");
            avcodec_send_packet(pC[pkts->stream_index], NULL);
            while(1)
            {
                dret = avcodec_receive_frame(pC[pkts->stream_index], rawFrame);
                if(dret == AVERROR_EOF) break;
                printf("dret: %d\n", dret);
            }
            avcodec_flush_buffers(pC[pkts->stream_index]);
        }
        else printf("avcodec_send_packet other error.\n");


        av_packet_free(&pkts);
        av_packet_free(&pktr);
        av_frame_free(&rawFrame);
        av_frame_unref(rawFrame);
    }



    if(av_write_trailer(ps2) == 0) printf("Wrote trailer\n");
}
********************************************

Thanks in advance.


More information about the Libav-user mailing list