[Libav-user] "Segmentation fault" When encoding H264 video frame

M N assemblerx86 at yandex.com
Thu Sep 15 22:28:15 EEST 2016


15.09.2016, 16:59, "Carl Eugen Hoyos" <ceffmpeg at gmail.com>:
>
> The line is here "if (!avctx->codec->encode2) {" indicating you did not
> initialize the parameter avctx sufficiently (setting up an encoder).
>
> Carl Eugen
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user

What I have done was initialize 2 AVCodecContext* arrays (As pointer to pointer), one for the decoder and one for the encoder, the number of AVCodecContext pointers depends on the number of streams in the input AVFormatContext. After that, when processing each stream, the encoder is opened using avcodec_open2(encodecontext[i], avcodec_find_encoder(decodecontext[i]->codec), NULL); (The same is done previously to the decodecontext.) This is done as many as the number of existing streams. Can you look at the code and tell me what I have done wrong? The reason why aac codec works for audio but avc/mp4 doesn't for video means the problem is not from my side, as it is working for another codec.
If you want it on pastebin for better highlighting of the code: http://pastebin.com/p405CjbJ
****************************************
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libavutil/rational.h>

#include <stdio.h>

int main()
{
    av_register_all();

    //av_log_set_level(-8);


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

    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;

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

        oStream = avformat_new_stream(ps2, NULL);
        //avcodec_parameters_copy(oStream->codecpar, iStream->codecpar);
        p2C[i] = oStream->codec;

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

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

            if(pC[i]->codec_type == AVMEDIA_TYPE_VIDEO) {
                                p2C[i]->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

                p2C[i]->height = pC[i]->height;
                p2C[i]->width = pC[i]->width;
                p2C[i]->sample_aspect_ratio = pC[i]->sample_aspect_ratio;
                p2C[i]->gop_size = pC[i]->gop_size;
                //take first format from list of supported formats
                if (encoder->pix_fmts)
                    p2C[i]->pix_fmt = encoder->pix_fmts[0];
                else
                    p2C[i]->pix_fmt = pC[i]->pix_fmt;
                //video time_base can be set to whatever is handy and supported by encoder
                oStream->time_base = iStream->time_base;
                p2C[i]->time_base = pC[i]->time_base;

            } else {
                                p2C[i]->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
                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];
                oStream->time_base = (AVRational){1, p2C[i]->sample_rate};
                p2C[i]->time_base = (AVRational){1, p2C[i]->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");

            avcodec_open2(pC[i], decoder, NULL);
            avcodec_open2(p2C[i], encoder, NULL);

            //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();
        AVPacket pktr;// = av_packet_alloc();
        AVFrame *rawFrame = av_frame_alloc();
        av_init_packet(&pkts);
        av_init_packet(&pktr);
        if(av_read_frame(ps, &pkts) != 0) break;

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

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

        int got_out;
        if(pkts.stream_index == 0)
        {

            if(avcodec_decode_video2(pC[pkts.stream_index], rawFrame, &got_out, &pkts) >= 0)
            {
                if(avcodec_encode_video2(p2C[pkts.stream_index], &pktr, rawFrame, &got_out) == 0)
                {
                    if(av_interleaved_write_frame(ps2, &pktr) == 0)
                    {
                        printf("SUCCESSFULLY WROTE PACKET\n");
                        //break;
                    }
                } else printf("Failed to encode video\n");
            } else printf("Failed to decode video\n");
        }
        else
        {
            if(avcodec_decode_audio4(pC[pkts.stream_index], rawFrame, &got_out, &pkts) >= 0)
            {
                if(avcodec_encode_audio2(p2C[pkts.stream_index], &pktr, rawFrame, &got_out) == 0)
                {
                    if(av_interleaved_write_frame(ps2, &pktr) == 0)
                    {
                        printf("SUCCESSFULLY WROTE PACKET\n");
                        //break;
                    }
                } else printf("Failed to encode audio\n");
            } else printf("Failed to decode audio\n");
        }
        av_frame_free(&rawFrame);
    }



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

****************************************


More information about the Libav-user mailing list