05.06.2013 14:39, Andrey Utkin пишет:
2013/6/5 Андрей <[email protected]>:
I use to compile the 32-bit version of ffmpeg visual studio 2012. I used the
latter for now build from 5/29/13.
This is my test code that reproduces the problem:

avcodec_register_all();

     int width = 764, height = 480;
     int got_output;
     AVFrame *frame;
     AVPacket pkt;
     AVCodec *codec;
     AVCodecContext *c = NULL;

     while(1)
     {
         frame = avcodec_alloc_frame();
         if (!frame) {
             fprintf(stderr, "Could not allocate video frame\n");
             return -1;
         }
         frame->format = AV_PIX_FMT_YUV420P;
         frame->width  = width;
         frame->height = height;

         /* the image can be allocated by any means and av_image_alloc() is
          * just the most convenient way if av_malloc() is to be used */
         int ret = av_image_alloc(frame->data, frame->linesize, width,
height,
                              AV_PIX_FMT_YUV420P, 1);
         if (ret < 0) {
             fprintf(stderr, "Could not allocate raw picture buffer\n");
             av_freep(&frame->data[0]);
             avcodec_free_frame(&frame);
             return -1;
         }

         /* find the mpeg4 video encoder */
         codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);
         if (!codec) {
             fprintf(stderr, "Codec not found\n");
             return -1;
         }

         c = avcodec_alloc_context3(codec);
         if (!c) {
             fprintf(stderr, "Could not allocate video codec context\n");
             return -1;
         }

         /* put sample parameters */
         c->profile = FF_PROFILE_MPEG4_SIMPLE;
         /* resolution must be a multiple of two */
         c->width = width;
         c->height = height;
         /* frames per second */
         c->time_base.den = 25;
         c->time_base.num = 1;
         c->gop_size = 25; /* emit one intra frame every 25 frames */
         c->pix_fmt = AV_PIX_FMT_YUV420P;
         c->qmax = 4;
         c->qmin = 4;

         /* open it */
         if (avcodec_open2(c, codec, NULL) < 0) {
             fprintf(stderr, "Could not open codec\n");
             avcodec_close(c);
You shouldn't avcodec_close() here. I think this can cause a problem.

             av_free(c);
             return -1;
         }

         for(int k = 0; k < 30; k++)
         {
             av_init_packet(&pkt);
             pkt.data = NULL;    // packet data will be allocated by the
encoder
             pkt.size = 0;

             frame->pts = c->frame_number;

             /* encode the image */
             if (avcodec_encode_video2(c, &pkt, frame, &got_output) < 0) {
                 fprintf(stderr, "Error encoding frame\n");
                 return -1;
             }

             if (got_output) {
                 av_free_packet(&pkt);
             }
         }

         if(c)
         {
             avcodec_close(c);
             av_free(c);
Can't say for sure, but av_free() seems redundant.

         }
         if(frame)
         {
             av_freep(&frame->data[0]);
             avcodec_free_frame(&frame);
Maybe there also something is redundant.

         }
     }

When you call function avcodec_close () throws an exception. Such an error
is detected on the MPEG4 codec with a frame width in the range 754-767 at an
altitude of 480. Perhaps at other resolutions, too. Help solve the problem.
...sorry for bad english
You have more than one call to avcodec_close(), do you know, which one
is executed?

Your code snippet should be easily compiled on linux, there you can
use valgrind memcheck tool, which makes debugging easy.
Also i suggest you to re-read avcodec.h and avformat.h for
explanations on how to release context objects correclty, some places
in your code are suspicious for me.

--
Andrey Utkin
_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user
Ok, for now I'm using video_encode_example from decoding_encoding.c example:

AVCodec *codec;
    AVCodecContext *c = NULL;
    int i, ret, x, y, got_output;
    AVFrame *frame;
    AVPacket pkt;

    /* register all the codecs */
    avcodec_register_all();

    /* find the mpeg1 video encoder */
    codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);
    if (!codec) {
        fprintf(stderr, "Codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }

    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 764;
    c->height = 480;
    /* frames per second */
    c->time_base.den = 25;
    c->time_base.num = 1;
    c->gop_size = 10; /* emit one intra frame every ten frames */
    c->max_b_frames = 1;
    c->pix_fmt = AV_PIX_FMT_YUV420P;

    /* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }

    frame = avcodec_alloc_frame();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;
    frame->width  = c->width;
    frame->height = c->height;

    /* the image can be allocated by any means and av_image_alloc() is
     * just the most convenient way if av_malloc() is to be used */
    ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height,
                         c->pix_fmt, 32);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate raw picture buffer\n");
        exit(1);
    }

    /* encode 1 second of video */
    for(i=0;i<25;i++) {
        av_init_packet(&pkt);
        pkt.data = NULL;    // packet data will be allocated by the encoder
        pkt.size = 0;

        fflush(stdout);
        /* prepare a dummy image */
        /* Y */
        for(y=0;y<c->height;y++) {
            for(x=0;x<c->width;x++) {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }

        /* Cb and Cr */
        for(y=0;y<c->height/2;y++) {
            for(x=0;x<c->width/2;x++) {
frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2; frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
            }
        }

        frame->pts = i;

        /* encode the image */
        ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }

        if (got_output) {
            av_free_packet(&pkt);
        }
    }

    avcodec_close(c);
    av_free(c);
    av_freep(&frame->data[0]);
    avcodec_free_frame(&frame);

The problem is that the context is not released correctly when the resolution is 764x480 and some other resolutions. If you use a different codec instead of MPEG4, such as H264, no error occurs if any resolution. I use the assembly under windows and unfortunately I do not have the possibility to compile the example under Linux to pinpoint the cause of the fall.
_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user

Reply via email to