[Libav-user] avcodec_close() crash

Андрей ashvyrkin at gosniias.ru
Fri Jun 14 16:27:21 CEST 2013


06.06.2013 7:53, Андрей пишет:
> 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.
*In the latest build of 14.06.13 the problem is solved.*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20130614/6fb3c425/attachment.html>


More information about the Libav-user mailing list