user60266: I want to publish image capture through ESP32-CAM to MQTT. Have following code :
#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include <StringArray.h>

#include <PubSubClient.h>
#include <base64.h>
#include <libb64/cencode.h>

// Replace with your network credentials
const char* ssid = "####";
const char* password = "####";

// Add your MQTT Broker IP address, example:
const char* mqtt_server = "###.cloudmqtt.com";
const int mqtt_port = 11073;
const char* mqtt_user = "###";
const char* mqtt_password = "###";

#define SLEEP_DELAY 10000 //Delay ofr 10 Sec
#define FILE_PHOTO "/photo.jpg"

// OV2640 camera module pins (CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22


//#define ESP32_CLIENT_ID = WiFi.macAddress()
//const char* esp_client_id = WiFi.macAddress()
WiFiClient mqttClient;
PubSubClient client(mqttClient);

const int LED_BUILTIN = 4;

void setup_camera() {
      // Turn-off the 'brownout detector'
      WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

      // OV2640 camera module
      camera_config_t config;
      config.ledc_channel = LEDC_CHANNEL_0;
      config.ledc_timer = LEDC_TIMER_0;
      config.pin_d0 = Y2_GPIO_NUM;
      config.pin_d1 = Y3_GPIO_NUM;
      config.pin_d2 = Y4_GPIO_NUM;
      config.pin_d3 = Y5_GPIO_NUM;
      config.pin_d4 = Y6_GPIO_NUM;
      config.pin_d5 = Y7_GPIO_NUM;
      config.pin_d6 = Y8_GPIO_NUM;
      config.pin_d7 = Y9_GPIO_NUM;
      config.pin_xclk = XCLK_GPIO_NUM;
      config.pin_pclk = PCLK_GPIO_NUM;
      config.pin_vsync = VSYNC_GPIO_NUM;
      config.pin_href = HREF_GPIO_NUM;
      config.pin_sscb_sda = SIOD_GPIO_NUM;
      config.pin_sscb_scl = SIOC_GPIO_NUM;
      config.pin_pwdn = PWDN_GPIO_NUM;
      config.pin_reset = RESET_GPIO_NUM;
      config.xclk_freq_hz = 20000000;
      config.pixel_format = PIXFORMAT_JPEG;

      if (psramFound()) {
        config.frame_size = FRAMESIZE_UXGA;
        config.jpeg_quality = 10;
        config.fb_count = 2;
      } else {
        config.frame_size = FRAMESIZE_SVGA;
        config.jpeg_quality = 12;
        config.fb_count = 1;
      }
      // Camera init
      esp_err_t err = esp_camera_init(&config);
      if (err != ESP_OK) {
        Serial.printf("Camera init failed with error 0x%x", err);
        ESP.restart();
      }
  }

// Capture Photo and Save it to SPIFFS
void capturePhoto( void ) {
  camera_fb_t * fb = NULL; // pointer
  bool ok = 0; // Boolean indicating if the picture has been taken correctly

  // Take a photo with the camera
  Serial.println("Taking a photo...");

  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

  Serial.print("Heap Size : ");
  Serial.println(ESP.getFreeHeap());
  //Serial.println(fb->format);
  Serial.print("fb len : ");
  Serial.println(fb->len);
  Serial.print("base64 encode expected len : ");
  Serial.println(base64_encode_expected_len(fb->len) + 1);
  String base64image = base64::encode(fb->buf, fb->len);
  Serial.print("base64 image : ");
  Serial.println(base64image);
  esp_camera_fb_return(fb);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address : ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  setup_camera();
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
  capturePhoto();
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  delay(SLEEP_DELAY);
}

This prints following to console 
Connecting to ####
...
WiFi connected
IP address : 192.168.1.247
PSRAM found: 1
Taking a photo...
Heap Size : 187548
fb len : 135966
base64 encode expected len : 181289
base64 image : -FAIL-

Update Feb 15 :
I tried following code 
void setup() {
  Serial.begin(115200);
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));
  Serial.print("Total heap: ");
  Serial.println(ESP.getHeapSize());
  Serial.print("Free heap: ");
  Serial.println(ESP.getFreeHeap());
  Serial.print("Total PSRAM: ");
  Serial.println(ESP.getPsramSize());
  Serial.print("Free PSRAM: ");
  Serial.println(ESP.getFreePsram());
}

which printed 
PSRAM found: 1
Total heap: 378748
Free heap: 352836
Total PSRAM: 4194252
Free PSRAM: 4194252

These are the board settings 
Board : AI Thinker ESP32 CAM
Latest board package :

I tried wit following board settings as well 
Board : ESP32 Dev Module
Upload Speed : 921600
CPU Frequency : 240 MHz
Flash Frequency : 80 MHz
Flash Mode : QIO
Flash Size : 4MB
Partition Scheme : Default 4MB with spiffs
Core Debug Level : Verbose
PSRAM : Enabled            
which also gives me following output 
[D][esp32-hal-psram.c:47] psramInit(): PSRAM enabled

Connecting to ###
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 4 - STA_CONNECTED
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 7 - STA_GOT_IP
[D][WiFiGeneric.cpp:381] _eventCallback(): STA IP: 192.168.1.247, MASK: 255.255.255.0, GW: 192.168.1.1
.
WiFi connected
IP address : 192.168.1.247
PSRAM found: 1
Taking a photo...
Heap Size : 187260
fb len : 101157
base64 encode expected len : 134877
base64 image : -FAIL-

From this output it looks like PSRAM is enabled. How can I use it for base64 encoded image ?
Also tried to add byte* psdRamBuffer = (byte*)ps_malloc(500000); mentioned at https://thingpulse.com/esp32-how-to-use-psram/ but didn't help.
I have this ESP32-CAM
Update :
I got following working, but it crashes for framesize_t resolution_ =FRAMESIZE_QXGA; that's why not able to capture 2 Megapixel picture.
#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include "SPIFFS.h"
#include "base64.h"
#include <PubSubClient.h>

// Replace with your network credentials
const char* ssid = "xxxxx";
const char* password = "xxxxx";

// Add your MQTT Broker IP address, example:
const char* mqtt_server = "xxxx.cloudmqtt.com";
const int mqtt_port = 1883;
const char* mqtt_user = "xxxx";
const char* mqtt_password = "xxxxx";

//topic name
const char* mqtt_TopicName = "/devices/esp32/data";


framesize_t resolution_ = FRAMESIZE_QVGA;


//use this delay 1000==1 second
#define SLEEP_DELAY 60000 //Delay ofr 60 Sec
#define FILE_PHOTO "/photo.jpg"

// OV2640 camera module pins (CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22


//#define ESP32_CLIENT_ID = WiFi.macAddress()
//const char* esp_client_id = WiFi.macAddress()
WiFiClient mqttClient;
PubSubClient client(mqttClient);

const int LED_BUILTIN = 4;

void setup_camera() {
      // Turn-off the 'brownout detector'
      WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

      // OV2640 camera module
      camera_config_t config;
      config.ledc_channel = LEDC_CHANNEL_0;
      config.ledc_timer = LEDC_TIMER_0;
      config.pin_d0 = Y2_GPIO_NUM;
      config.pin_d1 = Y3_GPIO_NUM;
      config.pin_d2 = Y4_GPIO_NUM;
      config.pin_d3 = Y5_GPIO_NUM;
      config.pin_d4 = Y6_GPIO_NUM;
      config.pin_d5 = Y7_GPIO_NUM;
      config.pin_d6 = Y8_GPIO_NUM;
      config.pin_d7 = Y9_GPIO_NUM;
      config.pin_xclk = XCLK_GPIO_NUM;
      config.pin_pclk = PCLK_GPIO_NUM;
      config.pin_vsync = VSYNC_GPIO_NUM;
      config.pin_href = HREF_GPIO_NUM;
      config.pin_sscb_sda = SIOD_GPIO_NUM;
      config.pin_sscb_scl = SIOC_GPIO_NUM;
      config.pin_pwdn = PWDN_GPIO_NUM;
      config.pin_reset = RESET_GPIO_NUM;
      config.xclk_freq_hz = 20000000;
      config.pixel_format = PIXFORMAT_JPEG;

      if (psramFound()) {
        config.frame_size = resolution_  ;// FRAMESIZE_UXGA;
        config.jpeg_quality = 10;
        config.fb_count = 1;
      } else {
        config.frame_size = FRAMESIZE_SVGA;
        config.jpeg_quality = 12;
        config.fb_count = 2;
      }
      // Camera init
      esp_err_t err = esp_camera_init(&config);
      if (err != ESP_OK) {
        Serial.printf("Camera init failed with error 0x%x", err);
        ESP.restart();
      }
  }

void publishTelemetryFromFile() {
  File file = SPIFFS.open("/b64image.txt", FILE_READ);
  if (!file) {
    Serial.println("There was an error opening the file for read");
    return;
  } else {
    Serial.println(String(file.size())+ "Byte");

  }

  char* data = (char*)heap_caps_malloc(file.size()+1, MALLOC_CAP_8BIT);
  if (data == NULL)
    Serial.println("Can not malloc memory");

  int i=0;

  //while(file.available()){
  for (i=0;i<file.size();i++){
    data[i] = file.read();

  }

  delay(10);

  //client.publish_P( mqtt_TopicName,"qwertyuiopasdfghjkl;zxcvbnm,", true);
  Serial.print( "Published to MQTT " + String(mqtt_server) + " server.." );
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  boolean Status=client.publish_P( mqtt_TopicName, (const uint8_t*)data, file.size(), true);
  Serial.println(String(Status? "Successfully":"Error") );

  free(data);
  file.close();
}

void capturePhoto( void ) {
   // Retrieve camera framebuffer
  camera_fb_t * fb = NULL;
  uint8_t* _jpg_buf = NULL;
  esp_err_t res = ESP_OK;
  size_t frame_size = 0;
  Serial.print("Capturing Image ..");

  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  fb = esp_camera_fb_get();
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
  if (!fb) {
    Serial.println("Camera capture failed");
    res = ESP_FAIL;
  } else {
    Serial.println("Done!");
    Serial.println(String("Size of the image...")+String(fb->len));

    {

      if(fb->format != PIXFORMAT_JPEG){
        Serial.println("Compressing");
        bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &frame_size);
        esp_camera_fb_return(fb);
        fb = NULL;
        if(!jpeg_converted){
          Serial.println("JPEG compression failed");
          res = ESP_FAIL;
        }
      } else {
        frame_size = fb->len;
        _jpg_buf = fb->buf;
        Serial.print("Size of the base64 encoded image...");

        my_base64_encode(_jpg_buf,fb->len,String("Sat Mar 28 11:47:01 EDT 2020") );
        esp_camera_fb_return(fb);
        publishTelemetryFromFile();

      }
    }
  }
  if (res != ESP_OK) {
 //   ESP_LOGW(TAG, "Camera capture failed with error = %d", err);

    return;
  }

 }

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address : ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(9600);

  //byte* psdRamBuffer = (byte*)ps_malloc(500000);
  setup_camera();
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
   if (!SPIFFS.begin(true)) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));

  capturePhoto();

  if (!client.connected()) {
    reconnect();
  }

  client.loop();
  delay(SLEEP_DELAY);
}


user30175: As you can see here, the definition of the return value for esp_camera_fb_get() is 
typedef struct {
    uint8_t * buf;              /*!< Pointer to the pixel data */
    size_t len;                 /*!< Length of the buffer in bytes */
    size_t width;               /*!< Width of the buffer in pixels */
    size_t height;              /*!< Height of the buffer in pixels */
    pixformat_t format;         /*!< Format of the pixel data */
} camera_fb_t;

..
camera_fb_t* esp_camera_fb_get();

..


typedef enum {
    PIXFORMAT_RGB565,    // 2BPP/RGB565
    PIXFORMAT_YUV422,    // 2BPP/YUV422
    PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
    PIXFORMAT_JPEG,      // JPEG/COMPRESSED
    PIXFORMAT_RGB888,    // 3BPP/RGB888
    PIXFORMAT_RAW,       // RAW
    PIXFORMAT_RGB444,    // 3BP2P/RGB444
    PIXFORMAT_RGB555,    // 3BP2P/RGB555
} pixformat_t;

Meaning that fb->buf and bf->len hold the raw data in the format specified by pixformat_t. Aka this is not a "string", these are raw bytes, which you can still base64-encode perfectly fine.
So for the base64 library 
    static String encode(const uint8_t * data, size_t length);

it already accepts the right data type and you can do
  fb = esp_camera_fb_get();  
  ..
  //will be allocated on the heap. Takes about 4/3 of the input size, so basically it doubles your memory requirements
  String imgDataB64 = base64::encode(fb->buf, fb->len);
  //add to a JSON object wit the metadata width, height and format so that it can be decoded

You should output the fb->format value to check what format the data is, and add this and the width & height information so that the image may be constructted on the other side. Beware high memory requierements since the base64 encoding basically creates a new buffer to store the base64 representation of it. That may be optimized by writing the framebuffer data into an initially bigger buffer which is then transformed in-place. But that would have to be changed at the image driver level.

60266: <p>I want to publish image capture through <a href="https://rads.stackoverflow.com/amzn/click/com/B07MDLFQH2" rel="nofollow noreferrer" rel="nofollow noreferrer">ESP32-CAM</a> to MQTT. Have following code :</p>

<pre><code>#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include &lt;StringArray.h&gt;

#include &lt;PubSubClient.h&gt;
#include &lt;base64.h&gt;
#include &lt;libb64/cencode.h&gt;

// Replace with your network credentials
const char* ssid = "####";
const char* password = "####";

// Add your MQTT Broker IP address, example:
const char* mqtt_server = "###.cloudmqtt.com";
const int mqtt_port = 11073;
const char* mqtt_user = "###";
const char* mqtt_password = "###";

#define SLEEP_DELAY 10000 //Delay ofr 10 Sec
#define FILE_PHOTO "/photo.jpg"

// OV2640 camera module pins (CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22


//#define ESP32_CLIENT_ID = WiFi.macAddress()
//const char* esp_client_id = WiFi.macAddress()
WiFiClient mqttClient;
PubSubClient client(mqttClient);

const int LED_BUILTIN = 4;

void setup_camera() {
      // Turn-off the 'brownout detector'
      WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

      // OV2640 camera module
      camera_config_t config;
      config.ledc_channel = LEDC_CHANNEL_0;
      config.ledc_timer = LEDC_TIMER_0;
      config.pin_d0 = Y2_GPIO_NUM;
      config.pin_d1 = Y3_GPIO_NUM;
      config.pin_d2 = Y4_GPIO_NUM;
      config.pin_d3 = Y5_GPIO_NUM;
      config.pin_d4 = Y6_GPIO_NUM;
      config.pin_d5 = Y7_GPIO_NUM;
      config.pin_d6 = Y8_GPIO_NUM;
      config.pin_d7 = Y9_GPIO_NUM;
      config.pin_xclk = XCLK_GPIO_NUM;
      config.pin_pclk = PCLK_GPIO_NUM;
      config.pin_vsync = VSYNC_GPIO_NUM;
      config.pin_href = HREF_GPIO_NUM;
      config.pin_sscb_sda = SIOD_GPIO_NUM;
      config.pin_sscb_scl = SIOC_GPIO_NUM;
      config.pin_pwdn = PWDN_GPIO_NUM;
      config.pin_reset = RESET_GPIO_NUM;
      config.xclk_freq_hz = 20000000;
      config.pixel_format = PIXFORMAT_JPEG;

      if (psramFound()) {
        config.frame_size = FRAMESIZE_UXGA;
        config.jpeg_quality = 10;
        config.fb_count = 2;
      } else {
        config.frame_size = FRAMESIZE_SVGA;
        config.jpeg_quality = 12;
        config.fb_count = 1;
      }
      // Camera init
      esp_err_t err = esp_camera_init(&amp;config);
      if (err != ESP_OK) {
        Serial.printf("Camera init failed with error 0x%x", err);
        ESP.restart();
      }
  }

// Capture Photo and Save it to SPIFFS
void capturePhoto( void ) {
  camera_fb_t * fb = NULL; // pointer
  bool ok = 0; // Boolean indicating if the picture has been taken correctly

  // Take a photo with the camera
  Serial.println("Taking a photo...");

  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

  Serial.print("Heap Size : ");
  Serial.println(ESP.getFreeHeap());
  //Serial.println(fb-&gt;format);
  Serial.print("fb len : ");
  Serial.println(fb-&gt;len);
  Serial.print("base64 encode expected len : ");
  Serial.println(base64_encode_expected_len(fb-&gt;len) + 1);
  String base64image = base64::encode(fb-&gt;buf, fb-&gt;len);
  Serial.print("base64 image : ");
  Serial.println(base64image);
  esp_camera_fb_return(fb);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address : ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  setup_camera();
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
  capturePhoto();
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  delay(SLEEP_DELAY);
}
</code></pre>

<p>This prints following to console </p>

<pre><code>Connecting to ####
...
WiFi connected
IP address : 192.168.1.247
PSRAM found: 1
Taking a photo...
Heap Size : 187548
fb len : 135966
base64 encode expected len : 181289
base64 image : -FAIL-
</code></pre>

<p><strong>Update Feb 15 :</strong></p>

<p>I tried following code </p>

<pre><code>void setup() {
  Serial.begin(115200);
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));
  Serial.print("Total heap: ");
  Serial.println(ESP.getHeapSize());
  Serial.print("Free heap: ");
  Serial.println(ESP.getFreeHeap());
  Serial.print("Total PSRAM: ");
  Serial.println(ESP.getPsramSize());
  Serial.print("Free PSRAM: ");
  Serial.println(ESP.getFreePsram());
}
</code></pre>

<p>which printed </p>

<pre><code>PSRAM found: 1
Total heap: 378748
Free heap: 352836
Total PSRAM: 4194252
Free PSRAM: 4194252
</code></pre>

<p>These are the board settings </p>

<p>Board : AI Thinker ESP32 CAM</p>

<p>Latest board package :
<a href="https://i.stack.imgur.com/pLI8t.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/pLI8t.png" alt="enter image description here"></a></p>

<p>I tried wit following board settings as well </p>

<p><strong>Board</strong> : ESP32 Dev Module<br>
<strong>Upload Speed</strong> : 921600<br>
<strong>CPU Frequency</strong> : 240 MHz<br>
<strong>Flash Frequency</strong> : 80 MHz<br>
<strong>Flash Mode</strong> : QIO<br>
<strong>Flash Size</strong> : 4MB<br>
<strong>Partition Scheme</strong> : Default 4MB with spiffs<br>
<strong>Core Debug Level</strong> : Verbose<br>
<strong>PSRAM</strong> : Enabled            </p>

<p>which also gives me following output </p>

<pre><code>[D][esp32-hal-psram.c:47] psramInit(): PSRAM enabled

Connecting to ###
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 4 - STA_CONNECTED
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 7 - STA_GOT_IP
[D][WiFiGeneric.cpp:381] _eventCallback(): STA IP: 192.168.1.247, MASK: 255.255.255.0, GW: 192.168.1.1
.
WiFi connected
IP address : 192.168.1.247
PSRAM found: 1
Taking a photo...
Heap Size : 187260
fb len : 101157
base64 encode expected len : 134877
base64 image : -FAIL-
</code></pre>

<p>From this output it looks like PSRAM is enabled. How can I use it for base64 encoded image ?</p>

<p>Also tried to add <code>byte* psdRamBuffer = (byte*)ps_malloc(500000);</code> mentioned at <a href="https://thingpulse.com/esp32-how-to-use-psram/" rel="nofollow noreferrer">https://thingpulse.com/esp32-how-to-use-psram/</a> but didn't help.</p>

<p>I have this <a href="https://rads.stackoverflow.com/amzn/click/com/B07MDLFQH2" rel="nofollow noreferrer" rel="nofollow noreferrer">ESP32-CAM</a></p>

<p>Update :</p>

<p>I got following working, but it crashes for <code>framesize_t resolution_ =FRAMESIZE_QXGA;</code> that's why not able to capture 2 Megapixel picture.</p>

<pre><code>#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include "SPIFFS.h"
#include "base64.h"
#include &lt;PubSubClient.h&gt;

// Replace with your network credentials
const char* ssid = "xxxxx";
const char* password = "xxxxx";

// Add your MQTT Broker IP address, example:
const char* mqtt_server = "xxxx.cloudmqtt.com";
const int mqtt_port = 1883;
const char* mqtt_user = "xxxx";
const char* mqtt_password = "xxxxx";

//topic name
const char* mqtt_TopicName = "/devices/esp32/data";


framesize_t resolution_ = FRAMESIZE_QVGA;


//use this delay 1000==1 second
#define SLEEP_DELAY 60000 //Delay ofr 60 Sec
#define FILE_PHOTO "/photo.jpg"

// OV2640 camera module pins (CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22


//#define ESP32_CLIENT_ID = WiFi.macAddress()
//const char* esp_client_id = WiFi.macAddress()
WiFiClient mqttClient;
PubSubClient client(mqttClient);

const int LED_BUILTIN = 4;

void setup_camera() {
      // Turn-off the 'brownout detector'
      WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

      // OV2640 camera module
      camera_config_t config;
      config.ledc_channel = LEDC_CHANNEL_0;
      config.ledc_timer = LEDC_TIMER_0;
      config.pin_d0 = Y2_GPIO_NUM;
      config.pin_d1 = Y3_GPIO_NUM;
      config.pin_d2 = Y4_GPIO_NUM;
      config.pin_d3 = Y5_GPIO_NUM;
      config.pin_d4 = Y6_GPIO_NUM;
      config.pin_d5 = Y7_GPIO_NUM;
      config.pin_d6 = Y8_GPIO_NUM;
      config.pin_d7 = Y9_GPIO_NUM;
      config.pin_xclk = XCLK_GPIO_NUM;
      config.pin_pclk = PCLK_GPIO_NUM;
      config.pin_vsync = VSYNC_GPIO_NUM;
      config.pin_href = HREF_GPIO_NUM;
      config.pin_sscb_sda = SIOD_GPIO_NUM;
      config.pin_sscb_scl = SIOC_GPIO_NUM;
      config.pin_pwdn = PWDN_GPIO_NUM;
      config.pin_reset = RESET_GPIO_NUM;
      config.xclk_freq_hz = 20000000;
      config.pixel_format = PIXFORMAT_JPEG;

      if (psramFound()) {
        config.frame_size = resolution_  ;// FRAMESIZE_UXGA;
        config.jpeg_quality = 10;
        config.fb_count = 1;
      } else {
        config.frame_size = FRAMESIZE_SVGA;
        config.jpeg_quality = 12;
        config.fb_count = 2;
      }
      // Camera init
      esp_err_t err = esp_camera_init(&amp;config);
      if (err != ESP_OK) {
        Serial.printf("Camera init failed with error 0x%x", err);
        ESP.restart();
      }
  }

void publishTelemetryFromFile() {
  File file = SPIFFS.open("/b64image.txt", FILE_READ);
  if (!file) {
    Serial.println("There was an error opening the file for read");
    return;
  } else {
    Serial.println(String(file.size())+ "Byte");

  }

  char* data = (char*)heap_caps_malloc(file.size()+1, MALLOC_CAP_8BIT);
  if (data == NULL)
    Serial.println("Can not malloc memory");

  int i=0;

  //while(file.available()){
  for (i=0;i&lt;file.size();i++){
    data[i] = file.read();

  }

  delay(10);

  //client.publish_P( mqtt_TopicName,"qwertyuiopasdfghjkl;zxcvbnm,", true);
  Serial.print( "Published to MQTT " + String(mqtt_server) + " server.." );
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  boolean Status=client.publish_P( mqtt_TopicName, (const uint8_t*)data, file.size(), true);
  Serial.println(String(Status? "Successfully":"Error") );

  free(data);
  file.close();
}

void capturePhoto( void ) {
   // Retrieve camera framebuffer
  camera_fb_t * fb = NULL;
  uint8_t* _jpg_buf = NULL;
  esp_err_t res = ESP_OK;
  size_t frame_size = 0;
  Serial.print("Capturing Image ..");

  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  fb = esp_camera_fb_get();
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
  if (!fb) {
    Serial.println("Camera capture failed");
    res = ESP_FAIL;
  } else {
    Serial.println("Done!");
    Serial.println(String("Size of the image...")+String(fb-&gt;len));

    {

      if(fb-&gt;format != PIXFORMAT_JPEG){
        Serial.println("Compressing");
        bool jpeg_converted = frame2jpg(fb, 80, &amp;_jpg_buf, &amp;frame_size);
        esp_camera_fb_return(fb);
        fb = NULL;
        if(!jpeg_converted){
          Serial.println("JPEG compression failed");
          res = ESP_FAIL;
        }
      } else {
        frame_size = fb-&gt;len;
        _jpg_buf = fb-&gt;buf;
        Serial.print("Size of the base64 encoded image...");

        my_base64_encode(_jpg_buf,fb-&gt;len,String("Sat Mar 28 11:47:01 EDT 2020") );
        esp_camera_fb_return(fb);
        publishTelemetryFromFile();

      }
    }
  }
  if (res != ESP_OK) {
 //   ESP_LOGW(TAG, "Camera capture failed with error = %d", err);

    return;
  }

 }

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address : ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(9600);

  //byte* psdRamBuffer = (byte*)ps_malloc(500000);
  setup_camera();
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
   if (!SPIFFS.begin(true)) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));

  capturePhoto();

  if (!client.connected()) {
    reconnect();
  }

  client.loop();
  delay(SLEEP_DELAY);
}
</code></pre>
 30175: <p>As you can see <a href="https://github.com/espressif/esp32-camera/blob/98669b337cb915ba2a154a73454eed7fbf8e4795/driver/include/esp_camera.h#L112-L118" rel="nofollow noreferrer">here</a>, the definition of the return value for <code>esp_camera_fb_get()</code> is </p>

<pre class="lang-cpp prettyprint-override"><code>typedef struct {
    uint8_t * buf;              /*!&lt; Pointer to the pixel data */
    size_t len;                 /*!&lt; Length of the buffer in bytes */
    size_t width;               /*!&lt; Width of the buffer in pixels */
    size_t height;              /*!&lt; Height of the buffer in pixels */
    pixformat_t format;         /*!&lt; Format of the pixel data */
} camera_fb_t;

..
camera_fb_t* esp_camera_fb_get();

..


typedef enum {
    PIXFORMAT_RGB565,    // 2BPP/RGB565
    PIXFORMAT_YUV422,    // 2BPP/YUV422
    PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
    PIXFORMAT_JPEG,      // JPEG/COMPRESSED
    PIXFORMAT_RGB888,    // 3BPP/RGB888
    PIXFORMAT_RAW,       // RAW
    PIXFORMAT_RGB444,    // 3BP2P/RGB444
    PIXFORMAT_RGB555,    // 3BP2P/RGB555
} pixformat_t;
</code></pre>

<p>Meaning that <code>fb-&gt;buf</code> and <code>bf-&gt;len</code> hold the raw data in the format specified by <code>pixformat_t</code>. Aka this is not a "string", these are raw bytes, which you can still base64-encode perfectly fine.</p>

<p>So for the base64 library </p>

<pre><code>    static String encode(const uint8_t * data, size_t length);
</code></pre>

<p>it already accepts the right data type and you can do</p>

<pre><code>  fb = esp_camera_fb_get();  
  ..
  //will be allocated on the heap. Takes about 4/3 of the input size, so basically it doubles your memory requirements
  String imgDataB64 = base64::encode(fb-&gt;buf, fb-&gt;len);
  //add to a JSON object wit the metadata width, height and format so that it can be decoded
</code></pre>

<p>You should output the <code>fb-&gt;format</code> value to check what format the data is, and add this and the width &amp; height information so that the image may be constructted on the other side. Beware high memory requierements since the base64 encoding basically creates a new buffer to store the base64 representation of it. That may be optimized by writing the framebuffer data into an initially bigger buffer which is then transformed in-place. But that would have to be changed at the image driver level.</p>
