title: std::Future_error when using std::promise
body: <p>I'm trying to make a video player. I have added a thread to time how long a video should be show on the screen. I'm trying to decode the video and update window in the main thread; the second thread will get the packets, see how long the packet should be displayed, and send the packet to main thread then wait for time to elapse.</p>
  
  <p>For some reason I get this error:</p>
  
  <pre><code>terminate called after throwing an instance of 'std::future_error'
    what():  std::future_error: No associated state
  </code></pre>
  
  <p>What's causing the error?</p>
  
  <p>My Code:</p>
  
  <pre><code>extern "C"{
      //FFmpeg libraries
      #include &lt;libavcodec/avcodec.h&gt;
      #include &lt;libavformat/avformat.h&gt;
      #include &lt;libswscale/swscale.h&gt;
  
      //SDL2 libraries
      #include &lt;SDL2/SDL.h&gt;
  }
  // compatibility with newer API
  #if LIBAVCODEC_VERSION_INT &lt; AV_VERSION_INT(55,28,1)
  #define av_frame_alloc avcodec_alloc_frame
  #define av_frame_free avcodec_free_frame
  #endif
  
  //C++ libraries
  #include &lt;memory&gt;
  #include &lt;stdio.h&gt;
  #include &lt;iostream&gt;
  #include &lt;chrono&gt;
  #include &lt;thread&gt;
  #include &lt;mutex&gt;
  #include &lt;condition_variable&gt;
  #include &lt;future&gt;
  
  
  typedef struct PacketQueue {
      AVPacketList *first_pkt, *last_pkt;
  } PacketQueue;
  
  std::atomic&lt;bool&gt;           quitting;
  std::mutex                  mutex;
  std::condition_variable     convar;
  
  int packet_queue_put(PacketQueue *q, AVPacket *pkt){
      AVPacketList *pkt1;
      if(av_dup_packet(pkt) &lt; 0){
          return -1;
      }
      pkt1 = (AVPacketList*) av_malloc(sizeof(AVPacketList));
      if(!pkt1){
          return -1;
      }
      pkt1-&gt;pkt = *pkt;
      pkt1-&gt;next = NULL;
  
      std::lock_guard&lt;std::mutex&gt; lock(mutex);
  
      if (!q-&gt;last_pkt){
          q-&gt;first_pkt = pkt1;
      }else{
          q-&gt;last_pkt-&gt;next = pkt1;
      }
      q-&gt;last_pkt = pkt1;
      convar.notify_all();
      return 0;
  }
  
  static int packet_queue_get(PacketQueue *q, AVPacket *pkt){
      AVPacketList *pkt1;
      int ret;
  
      std::unique_lock&lt;std::mutex&gt; lk(mutex);
      while(1){
          if(quitting){
              ret = -1;
              break;
          }
  
          pkt1 = q-&gt;first_pkt;
          if(pkt1){
              q-&gt;first_pkt = pkt1-&gt;next;
              if(!q-&gt;first_pkt){
                  q-&gt;last_pkt = NULL;
              }
              *pkt = pkt1-&gt;pkt;
              av_free(pkt1);
              ret = 1;
              break;
          }else {
              convar.wait_for(lk, std::chrono::milliseconds(1));
          }
      }
      return ret;
  }
  
  void videoTimerFunc(AVRational time_base, PacketQueue* videoq, std::promise&lt;AVPacket&gt; prms){
      AVPacket pkt;
      int64_t last_pts = 0;
      int64_t frameDelay;
      AVRational microseconds = {1, 1000000};
  
      while(!quitting){
          // Getting packet and check if there are more packets
          if(!packet_queue_get(videoq, &amp;pkt)){
              // Close programme
              quitting = true;
          }else {
              // Send packet and create timer
              frameDelay = av_rescale_q(pkt.dts, time_base, microseconds) - last_pts;
              last_pts = av_rescale_q(pkt.dts, time_base, microseconds);
              prms.set_value(pkt);
  
              std::this_thread::sleep_for(std::chrono::microseconds(frameDelay));
          }
      }
  }
  
  int main(int argc, char *argv[]){
  AVFormatContext*                FormatCtx = nullptr;
  AVCodecContext*                 CodecCtxOrig = nullptr;
  AVCodecContext*                 CodecCtx = nullptr;
  AVCodec*                        Codec = nullptr;
  int                             videoStream;
  AVFrame*                        Frame = nullptr;
  AVPacket                        packet;
  struct SwsContext*              SwsCtx = nullptr;
  
  PacketQueue                     videoq;
  std::promise&lt;AVPacket&gt;          pktprms;
  std::future&lt;AVPacket&gt;           pktftr = pktprms.get_future();
  int                             frameFinished;
  int64_t                         lastPTS;
  
  SDL_Event                       event;
  SDL_Window*                     screen;
  SDL_Renderer*                   renderer;
  SDL_Texture*                    texture;
  std::shared_ptr&lt;Uint8&gt;          yPlane, uPlane, vPlane;
  int                             uvPitch;
  
  if (argc != 2) {
      fprintf(stderr, "Usage: %s &lt;file&gt;\n", argv[0]);
      return -1;
  }
  
  // Register all formats and codecs
  av_register_all();
  
  // Initialise SDL2
  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
      fprintf(stderr, "Couldn't initialise SDL - %s\n", SDL_GetError());
      return -1;
  }
  
  // Setting things up
  quitting = false;
  memset(&amp;videoq, 0, sizeof(PacketQueue));
  
  // Open video file
  if(avformat_open_input(&amp;FormatCtx, argv[1], NULL, NULL) != 0){
      fprintf(stderr, "Couldn't open file\n");        
      return -1; // Couldn't open file
  }
  
  // Retrieve stream information
  if(avformat_find_stream_info(FormatCtx, NULL) &lt; 0){
      fprintf(stderr, "Couldn't find stream information\n");
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
  
      return -1; // Couldn't find stream information
  }
  
  // Find the video stream
  videoStream = av_find_best_stream(FormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
  if(videoStream &lt; 0){
      fprintf(stderr, "Couldn't find video stream\n");
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
  
      return -1; // Didn't find a video stream
  }
  
  // Get a pointer to the codec context for the video stream
  CodecCtxOrig = FormatCtx-&gt;streams[videoStream]-&gt;codec;
  
  // Find the decoder for the video stream
  Codec = avcodec_find_decoder(CodecCtxOrig-&gt;codec_id);
  if(Codec == NULL){
      fprintf(stderr, "Unsupported codec\n");
  
      // Close the codec
      avcodec_close(CodecCtxOrig);
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
  
      return -1; // Codec not found
  }
  
  // Copy context
  CodecCtx = avcodec_alloc_context3(Codec);
  if(avcodec_copy_context(CodecCtx, CodecCtxOrig) != 0){
      fprintf(stderr, "Couldn't copy codec context");
  
      // Close the codec
      avcodec_close(CodecCtxOrig);
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
  
      return -1; // Error copying codec context
  }
  
  // Open codec
  if(avcodec_open2(CodecCtx, Codec, NULL) &lt; 0){
      fprintf(stderr, "Couldn't open codec\n");
  
      // Close the codec
      avcodec_close(CodecCtx);
      avcodec_close(CodecCtxOrig);
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
      return -1; // Could not open codec
  }
  
  // Allocate video frame
  Frame = av_frame_alloc();
  
  // Make a screen to put our video
  screen = SDL_CreateWindow("Video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CodecCtx-&gt;width, CodecCtx-&gt;height, 0);
  if(!screen){
      fprintf(stderr, "SDL: could not create window - exiting\n");
      quitting = true;
  
      // Clean up SDL2
      SDL_Quit();
  
      // Free the YUV frame
      av_frame_free(&amp;Frame);
  
      // Close the codec
      avcodec_close(CodecCtx);
      avcodec_close(CodecCtxOrig);
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
  
      return -1;
  }
  
  renderer = SDL_CreateRenderer(screen, -1, 0);
  if(!renderer){
      fprintf(stderr, "SDL: could not create renderer - exiting\n");
      quitting = true;
  
      // Clean up SDL2
      SDL_DestroyWindow(screen);
      SDL_Quit();
  
      // Free the YUV frame
      av_frame_free(&amp;Frame);
  
      // Close the codec
      avcodec_close(CodecCtx);
      avcodec_close(CodecCtxOrig);
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
      return -1;
  }
  
  // Allocate a place to put our YUV image on that screen
  texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, CodecCtx-&gt;width, CodecCtx-&gt;height);
  if(!texture){
      fprintf(stderr, "SDL: could not create texture - exiting\n");
      quitting = true;
  
      // Clean up SDL2
      SDL_DestroyRenderer(renderer);
      SDL_DestroyWindow(screen);
      SDL_Quit();
  
      // Free the YUV frame
      av_frame_free(&amp;Frame);
  
      // Close the codec
      avcodec_close(CodecCtx);
      avcodec_close(CodecCtxOrig);
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
      return -1;
  }
  
  // Initialise SWS context for software scaling
  SwsCtx = sws_getContext(CodecCtx-&gt;width, CodecCtx-&gt;height, CodecCtx-&gt;pix_fmt,
              CodecCtx-&gt;width, CodecCtx-&gt;height, PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL);
  if(!SwsCtx){
      fprintf(stderr, "Couldn't create sws context\n");
      quitting = true;
  
      // Clean up SDL2
      SDL_DestroyTexture(texture);
      SDL_DestroyRenderer(renderer);
      SDL_DestroyWindow(screen);
      SDL_Quit();
  
      // Free the YUV frame
      av_frame_free(&amp;Frame);
  
      // Close the codec
      avcodec_close(CodecCtx);
      avcodec_close(CodecCtxOrig);
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
      return -1;
  }
  
  // set up YV12 pixel array (12 bits per pixel)
  yPlane = std::shared_ptr&lt;Uint8&gt;((Uint8 *)::operator new (CodecCtx-&gt;width * CodecCtx-&gt;height, std::nothrow));
  uPlane = std::shared_ptr&lt;Uint8&gt;((Uint8 *)::operator new (CodecCtx-&gt;width * CodecCtx-&gt;height / 4, std::nothrow));
  vPlane = std::shared_ptr&lt;Uint8&gt;((Uint8 *)::operator new (CodecCtx-&gt;width * CodecCtx-&gt;height / 4, std::nothrow));
  uvPitch = CodecCtx-&gt;width / 2;
  
  if (!yPlane || !uPlane || !vPlane) {
      fprintf(stderr, "Could not allocate pixel buffers - exiting\n");
      quitting = true;
  
      // Clean up SDL2
      SDL_DestroyTexture(texture);
      SDL_DestroyRenderer(renderer);
      SDL_DestroyWindow(screen);
      SDL_Quit();
  
      // Free the YUV frame
      av_frame_free(&amp;Frame);
  
      // Close the codec
      avcodec_close(CodecCtx);
      avcodec_close(CodecCtxOrig);
  
      // Close the video file
      avformat_close_input(&amp;FormatCtx);
      return -1;
  }
  
  std::thread videoTimerThread(videoTimerFunc, FormatCtx-&gt;streams[videoStream]-&gt;time_base, &amp;videoq, std::move(pktprms));
  
  while (!quitting) {
      // Check for more packets
      if(av_read_frame(FormatCtx, &amp;packet) &gt;= 0){
          // Check what stream it belongs to
          if (packet.stream_index == videoStream) {
              packet_queue_put(&amp;videoq, &amp;packet);
          }else{
              // Free the packet that was allocated by av_read_frame
              av_free_packet(&amp;packet);
          }
      }
  
      // Check if its time to update
      if(pktftr.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready){
          // Getting packet
          packet = pktftr.get();
  
          // Decode video frame
          avcodec_decode_video2(CodecCtx, Frame, &amp;frameFinished, &amp;packet);
  
          // Did we get a video frame?
          if (frameFinished) {
              AVPicture pict;
              pict.data[0] = yPlane.get();
              pict.data[1] = uPlane.get();
              pict.data[2] = vPlane.get();
              pict.linesize[0] = CodecCtx-&gt;width;
              pict.linesize[1] = uvPitch;
              pict.linesize[2] = uvPitch;
  
              // Convert the image into YUV format that SDL uses
              sws_scale(SwsCtx, (uint8_t const * const *) Frame-&gt;data, Frame-&gt;linesize, 0, CodecCtx-&gt;height, pict.data, pict.linesize);
  
              SDL_UpdateYUVTexture(texture, NULL, yPlane.get(), CodecCtx-&gt;width, uPlane.get(), uvPitch, vPlane.get(), uvPitch);
  
              SDL_RenderClear(renderer);
              SDL_RenderCopy(renderer, texture, NULL, NULL);
              SDL_RenderPresent(renderer);
          }
          // Free the packet that was allocated by av_read_frame
          av_free_packet(&amp;packet);
      }
  
      SDL_PollEvent(&amp;event);
      switch (event.type) {
          case SDL_QUIT:
              quitting = true;
              break;
          default:
              break;
      }
  }
  
  videoTimerThread.join();
  
  //SDL2 clean up
  SDL_DestroyTexture(texture);
  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(screen);
  SDL_Quit();
  
  // Free the YUV frame
  av_frame_free(&amp;Frame);
  
  // Free Sws
  sws_freeContext(SwsCtx);
  
  // Close the codec
  avcodec_close(CodecCtx);
  avcodec_close(CodecCtxOrig);
  
  // Close the video file
  avformat_close_input(&amp;FormatCtx);
  
  return 0;
  }
  </code></pre>