[Libav-user] avcodec_close() crash

Андрей ashvyrkin at gosniias.ru
Thu Jun 6 05:53:45 CEST 2013


05.06.2013 14:39, Andrey Utkin пишет:
> 2013/6/5 Андрей <ashvyrkin at gosniias.ru>:
>> 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
> Libav-user at ffmpeg.org
> 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.


More information about the Libav-user mailing list