c ++ / cli应用程序中的内存泄漏

时间:2013-12-10 15:58:49

标签: c# ffmpeg c++-cli

我将位图从我的c#app传递到c ++ / cli dll,将其添加到视频中。 问题是程序慢慢泄漏内存。我试过_CrtDumpMemoryLeaks()显示我的位图泄漏&另外40字节泄漏,但我正在处理位图。 任何人都可以看到内存泄漏,这是代码..

流速:

1)通过takescreenshot()获取截图

2)将其传递给c ++ / cli函数

3)配置位图

来自我的c#app的行

Bitmap snap = takescreeshot();
vencoder.AddBitmap(snap);
snap.Dispose();
vencoder.printleak();

private static Bitmap takescreeshot()
    {
        System.Drawing.Bitmap bitmap = null;
        System.Drawing.Graphics graphics = null;

        bitmap = new Bitmap
        (
            System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
            System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height,
            System.Drawing.Imaging.PixelFormat.Format24bppRgb
        );

        graphics = System.Drawing.Graphics.FromImage(bitmap);

        graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size);

        //Write TimeSpamp
        Rectangle rect = new Rectangle(1166, 738, 200, 20);
        String datetime= System.String.Format("{0:dd:MM:yy  hh:mm:ss}",DateTime.Now);
        System.Drawing.Font sysfont = new System.Drawing.Font("Times New Roman", 14, FontStyle.Bold);
        graphics.DrawString(datetime, sysfont, Brushes.Red,rect);
        //

        Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721);
        Bitmap grayImage = filter.Apply(bitmap);

        //Dispose
        bitmap.Dispose();
        graphics.Dispose();

        return grayImage;
    }

现在在c ++ / cli dll

bool VideoEncoder::AddBitmap(Bitmap^ bitmap)
    {
        BitmapData^ bitmapData = bitmap->LockBits( System::Drawing::Rectangle( 0, 0,bitmap->Width, bitmap->Height ),ImageLockMode::ReadOnly,PixelFormat::Format8bppIndexed);
        uint8_t* ptr = reinterpret_cast<uint8_t*>( static_cast<void*>( bitmapData->Scan0 ) );
        uint8_t* srcData[4] = { ptr, NULL, NULL, NULL };
        int srcLinesize[4] = { bitmapData->Stride, 0, 0, 0 };

        pCurrentPicture = CreateFFmpegPicture(pVideoStream->codec->pix_fmt, pVideoStream->codec->width, pVideoStream->codec->height);

        sws_scale(pImgConvertCtx, srcData, srcLinesize, 0, bitmap->Height, pCurrentPicture->data, pCurrentPicture->linesize );

        bitmap->UnlockBits( bitmapData );

        write_video_frame();

        bitmapData=nullptr;
        ptr=NULL;

        return true;
    }

AVFrame * VideoEncoder::CreateFFmpegPicture(int pix_fmt, int nWidth, int nHeight)
    {

      AVFrame *picture     = NULL;
      uint8_t *picture_buf = NULL;
      int size;

      picture = avcodec_alloc_frame();
      if ( !picture)
      {
        printf("Cannot create frame\n");
        return NULL;
      }

      size = avpicture_get_size((AVPixelFormat)pix_fmt, nWidth, nHeight);

      picture_buf = (uint8_t *) av_malloc(size);

      if (!picture_buf) 
      {
        av_free(picture);
        printf("Cannot allocate buffer\n");
        return NULL;
      }

      avpicture_fill((AVPicture *)picture, picture_buf,
        (AVPixelFormat)pix_fmt, nWidth, nHeight);

      return picture;
    }

    void VideoEncoder::write_video_frame()
    {
        AVCodecContext* codecContext = pVideoStream->codec;

        int out_size, ret = 0;

        if ( pFormatContext->oformat->flags & AVFMT_RAWPICTURE )
        {
            printf( "raw picture must be written" );
        }
        else
        {
            out_size = avcodec_encode_video( codecContext, pVideoEncodeBuffer,nSizeVideoEncodeBuffer, pCurrentPicture );

            if ( out_size > 0 )
            {
                AVPacket packet;
                av_init_packet( &packet );

                if ( codecContext->coded_frame->pts != AV_NOPTS_VALUE )
                {
                    packet.pts = av_rescale_q( packet.pts, codecContext->time_base, pVideoStream->time_base );
                }

                if ( codecContext->coded_frame->pkt_dts != AV_NOPTS_VALUE )
                {
                    packet.dts = av_rescale_q( packet.dts, codecContext->time_base, pVideoStream->time_base );
                }

                if ( codecContext->coded_frame->key_frame )
                {
                    packet.flags |= AV_PKT_FLAG_KEY;
                }

                packet.stream_index = pVideoStream->index;
                packet.data = pVideoEncodeBuffer;
                packet.size = out_size;

                ret = av_interleaved_write_frame( pFormatContext, &packet );

                av_free_packet(&packet);
                av_freep(pCurrentPicture);
            }
            else
            {
                // image was buffered
            }
        }

        if ( ret != 0 )
        {
            throw gcnew Exception( "Error while writing video frame." );
        }
    }


    void VideoEncoder::printleak()
    {
        printf("No of leaks: %d",_CrtDumpMemoryLeaks());
        printf("\n");
    }

0 个答案:

没有答案