/** Method that destroy the references of this class */
  public void recycle() {
    // Destroy the media discovery task
    mPictureDiscoverer.recycle();
    synchronized (mEffectsSync) {
      if (mEffects != null) {
        mEffects.release();
      }
      if (mBorders != null) {
        mBorders.release();
      }
    }

    // Destroy the background task
    if (mBackgroundTask != null) {
      mBackgroundTask.mRun = false;
      try {
        synchronized (mBackgroundTask.mLoadSync) {
          mBackgroundTask.interrupt();
        }
      } catch (Exception e) {
        // Ignore
      }
    }
    mBackgroundTask = null;
  }
  /**
   * Method that load the gles texture and apply to the requestor frame (which includes fix the
   * aspect ratio and/or effects and borders)
   *
   * @param requestor The requestor target
   * @param ti The original texture information (the one with the bitmap one)
   */
  private void applyToRequestor(TextureRequestor requestor, GLESTextureInfo ti) {
    // Transform requestor dimensions to screen dimensions
    RectF dimens = requestor.getRequestorDimensions();
    Rect pixels =
        new Rect(
            0,
            0,
            (int) (mScreenDimensions.width() * dimens.width() / 2),
            (int) (mScreenDimensions.height() * dimens.height() / 2));

    final Disposition disposition = requestor.getDisposition();
    synchronized (mEffectsSync) {
      if (disposition.hasFlag(Disposition.EFFECT_FLAG)) {
        ti.effect = mEffects.getNextEffect();
      }
      if (disposition.hasFlag(Disposition.BORDER_FLAG)) {
        ti.border = mBorders.getNextBorder();
      }
    }

    // Check if we have to apply any correction to the image
    GLESTextureInfo dst;
    if (ti.bitmap != null && Preferences.General.isFixAspectRatio(mContext)) {

      // Create a texture of power of two here to avoid scaling the bitmap twice
      int w = pixels.width();
      int h = pixels.height();
      if (!BitmapUtils.isPowerOfTwo(w, h)
          && PreferencesProvider.Preferences.General.isPowerOfTwo(mContext)) {
        w = h = BitmapUtils.calculateUpperPowerOfTwo(Math.min(w, h));
      }

      // Create a thumbnail of the image
      Bitmap thumb = BitmapUtils.createScaledBitmap(ti.bitmap, w, h, BitmapUtils.ScalingLogic.CROP);
      if (!thumb.equals(ti.bitmap)) {
        ti.bitmap.recycle();
      }
      dst = GLESUtil.loadTexture(mContext, thumb, ti.effect, ti.border, pixels);
    } else {
      // Load the texture without any correction
      dst = GLESUtil.loadTexture(mContext, ti.bitmap, ti.effect, ti.border, pixels);
    }

    // Swap references
    ti.bitmap = dst.bitmap;
    ti.handle = dst.handle;
    ti.effect = null;
    ti.border = null;
    dst.handle = 0;
    dst.bitmap = null;

    // And notify to the requestor
    requestor.setTextureHandle(ti);

    // Clean up memory
    if (ti.bitmap != null) {
      ti.bitmap.recycle();
      ti.bitmap = null;
    }
  }
 /**
  * Method that update the effect context if the EGL context change
  *
  * @param effectCtx The new effect context
  */
 public void updateEffectContext(final EffectContext effectCtx) {
   synchronized (mEffectsSync) {
     if (mEffects != null) {
       mEffects.release();
       mEffects = null;
     }
     mEffects = new Effects(mContext, effectCtx);
     if (mBorders != null) {
       mBorders.release();
       mBorders = null;
     }
     mBorders = new Borders(mContext, effectCtx);
   }
   emptyTextureQueue(true);
 }