bool add_sao_tasks(image_unit* imgunit, int saoInputProgress)
{
  de265_image* img = imgunit->img;
  const seq_parameter_set& sps = img->get_sps();

  if (sps.sample_adaptive_offset_enabled_flag==0) {
    return false;
  }


  decoder_context* ctx = img->decctx;

  de265_error err = imgunit->sao_output.alloc_image(img->get_width(), img->get_height(),
                                                    img->get_chroma_format(),
                                                    img->get_shared_sps(),
                                                    false,
                                                    img->decctx, //img->encctx,
                                                    img->pts, img->user_data, true);
  if (err != DE265_OK) {
    img->decctx->add_warning(DE265_WARNING_CANNOT_APPLY_SAO_OUT_OF_MEMORY,false);
    return false;
  }

  int nRows = sps.PicHeightInCtbsY;

  int n=0;
  img->thread_start(nRows);

  for (int y=0;y<nRows;y++)
    {
      thread_task_sao* task = new thread_task_sao;

      task->inputImg  = img;
      task->outputImg = &imgunit->sao_output;
      task->img = img;
      task->ctb_y = y;
      task->inputProgress = saoInputProgress;

      imgunit->tasks.push_back(task);
      add_task(&ctx->thread_pool_, task);
      n++;
    }

  /* Currently need barrier here because when are finished, we have to swap the pixel
     data back into the main image. */
  img->wait_for_completion();

  img->exchange_pixel_data_with(imgunit->sao_output);

  return true;
}
bool add_sao_tasks(image_unit* imgunit, int saoInputProgress)
{
  de265_image* img = imgunit->img;
  const seq_parameter_set& sps = img->get_sps();

  if (sps.sample_adaptive_offset_enabled_flag==0) {
    return false;
  }


  decoder_context* ctx = img->decctx;

  de265_error err = imgunit->sao_output.alloc_image(img->get_width(), img->get_height(),
                                                    img->get_chroma_format(),
                                                    img->get_shared_sps(),
                                                    false,
                                                    img->decctx,  
                                                    img->pts, img->user_data, true);
  if (err != DE265_OK) {
    img->decctx->add_warning(DE265_WARNING_CANNOT_APPLY_SAO_OUT_OF_MEMORY,false);
    return false;
  }

  int nRows = sps.PicHeightInCtbsY;

  int n=0;
  img->thread_start(nRows);

  for (int y=0;y<nRows;y++)
    {
      thread_task_sao* task = new thread_task_sao;

      task->inputImg  = img;
      task->outputImg = &imgunit->sao_output;
      task->img = img;
      task->ctb_y = y;
      task->inputProgress = saoInputProgress;

      imgunit->tasks.push_back(task);
      add_task(&ctx->thread_pool_, task);
      n++;
    }

   
  img->wait_for_completion();

  img->exchange_pixel_data_with(imgunit->sao_output);

  return true;
}