title: Decode a video file from memory using libav
body: <p>Supose I have an entire video file in memory and I want to use libav to decode the whole frames. How should I do it? The point is that I can do it reading directly from a file using avformat_open_input() function but I do need to do it from a file which is stored in memory.</p>
  
  <p>My AVIOContext implementation:</p>
  
  <pre><code>class AVIOMemContext
  {
  
  public:
  
      AVIOMemContext(char* videoData, const int videoLen)
      {
          // Output buffer
          bufferSize = 32768;
          buffer = static_cast&lt;char*&gt;(av_malloc(bufferSize));
  
          // Internal buffer
          pos = 0;
          this-&gt;videoData = videoData;
          this-&gt;videoLen = videoLen;
  
          ctx_ = avio_alloc_context((unsigned char*) buffer, bufferSize, AVIO_FLAG_READ, this, &amp;AVIOMemContext::read, &amp;AVIOMemContext::write, &amp;AVIOMemContext::seek);
      }
  
      ~AVIOMemContext()
      {
          av_free(videoData);
      }
  
      static int read(void *opaque, unsigned char *buf, int buf_size)
      {
          AVIOMemContext* This = static_cast&lt;AVIOMemContext*&gt;(opaque);
  
          // Read from pos to pos + buf_size
          if (This-&gt;pos + buf_size &gt; This-&gt;videoLen)
          {
              int len = This-&gt;videoLen - This-&gt;pos;
              memcpy(buf, This-&gt;videoData + This-&gt;pos, len);
              return len;
          }
          else
          {
              memcpy(buf, This-&gt;videoData + This-&gt;pos, buf_size);
              return buf_size;
          }
      }
  
      static int write(void *opaque, unsigned char *buf, int buf_size)
      {
          /*
          AVIOMemContext* This = static_cast&lt;AVIOMemContext*&gt;(opaque);
          return fwrite(buf, 1, buf_size, This-&gt;f_);
          */
  
          return 0;
      }
  
      static int64_t seek(void *opaque, int64_t offset, int whence)
      {
          AVIOMemContext* This = static_cast&lt;AVIOMemContext*&gt;(opaque);
  
          if (offset + whence &gt; This-&gt;videoLen)
          {
              This-&gt;pos = This-&gt;videoLen;
  
              return -1;
          }
          else
          {
              This-&gt;pos = offset + whence;
  
              return 0;
          }
      }
  
      AVIOContext *get_avio()
      {
          return ctx_;
      }
  
  private:
  
      // Output buffer
      int bufferSize;
      char* buffer;
  
      // Internal buffer
      int pos;
      char* videoData;
      int videoLen;
  
      AVIOContext* ctx_;
  
  };
  </code></pre>
  
  <p>My current code:</p>
  
  <pre><code>[...]
  
  av_register_all();
  avcodec_register_all();
  
  AVFormatContext* context;
  AVCodec* pCodec;
  AVPacket packet;
  AVCodecContext* pCodecCtx;
  int video_stream_index;
  int res;
  int got_picture;
  
  // Init variables and objects
  context = avformat_alloc_context();
  
  AVIOMemContext priv_ctx(videoData, videoLen); 
  context-&gt;pb = priv_ctx.get_avio();
  
  res = avformat_find_stream_info(context, NULL);
  
  if (res &lt; 0)
  {
      // Error
      avformat_free_context(context);
  
      return 0;
  }
  
  // Obtain the video stream of the total set of streams
  for (unsigned int k = 0; k &lt; context-&gt;nb_streams; ++k)
  {
      if (context-&gt;streams[k]-&gt;codec-&gt;codec_type == AVMEDIA_TYPE_VIDEO)
          video_stream_index = k;
      context-&gt;streams[k]-&gt;codec-&gt;time_base.den = 90000;
  }
  
  pCodecCtx = context-&gt;streams[video_stream_index]-&gt;codec;
  pCodec = avcodec_find_decoder(pCodecCtx-&gt;codec_id);
  
  avcodec_open(pCodecCtx, pCodec);
  
  //allocate video frame
  AVFrame *pFrame = avcodec_alloc_frame();
  
  unsigned int nFrame = 0;
  
  while (av_read_frame(context, &amp;packet) &gt;= 0)
  
  [...]
  </code></pre>
  
  <p>Thanks in advance,</p>
  
  <p>Dídac Pérez</p>