title: What to pass to avcodec_decode_video2 for H.264 Transport Stream?
body: <p>I want to decode H.264 video from a collection of MPEG-2 Transport Stream packets but I am not clear what to pass to <code>avcodec_decode_video2</code></p>
  
  <p><a href="https://www.ffmpeg.org/doxygen/2.7/group__lavc__decoding.html#ga99ee61b6dcffb7817a275d39da58cc74" rel="nofollow noreferrer">The documentation</a> says to pass "the input AVPacket containing the input buffer."</p>
  
  <p>But what should be in the input buffer?</p>
  
  <p>A PES packet will be spread across the payload portion of several TS packets, with NALU(s) inside the PES. So pass a TS fragment? The entire PES? PES payload only?</p>
  
  <p>This <a href="https://fossies.org/linux/ffmpeg/doc/examples/decoding_encoding.c" rel="nofollow noreferrer">Sample Code</a> mentions:</p>
  
  <blockquote>
    <p>BUT some other codecs (msmpeg4, mpeg4) are inherently frame based, so
    you must call them with all the data for one frame exactly. You must
    also initialize 'width' and 'height' before initializing them. </p>
  </blockquote>
  
  <p>But I can find no info on what "all the data" means...</p>
  
  <p>Passing a fragment of a TS packet payload is not working:</p>
  
  <pre><code>AVPacket avDecPkt;
  av_init_packet(&amp;avDecPkt);
  avDecPkt.data = inbuf_ptr;
  avDecPkt.size = esBufSize;
  
  len = avcodec_decode_video2(mpDecoderContext, mpFrameDec, &amp;got_picture, &amp;avDecPkt);
  if (len &lt; 0)
  {
      printf("  TS PKT #%.0f. Error decoding frame #%04d [rc=%d '%s']\n",
          tsPacket.pktNum, mDecodedFrameNum, len, av_make_error_string(errMsg, 128, len));
      return;
  }
  </code></pre>
  
  <p><strong>output</strong></p>
  
  <pre><code>[h264 @ 0x81cd2a0] no frame!
  TS PKT #2973. Error decoding frame #0001 [rc=-1094995529 'Invalid data found when processing input']
  </code></pre>
  
  <p><strong>EDIT</strong></p>
  
  <p>Using the excellent hits from WLGfx, I made this simple program to try decoding TS packets.  As input, I prepared a file containing <strong>only</strong> TS packets from the Video PID.</p>
  
  <p>It feels close but I don't know how to set up the FormatContext.  The code below segfaults at av_read_frame() (and internally at <code>ret = s-&gt;iformat-&gt;read_packet(s, pkt)</code>).  s->iformat is zero.</p>
  
  <p>Suggestions?</p>
  
  <p><strong>EDIT II - Sorry, for got post source code **
  **EDIT III - Sample code updated to simulate reading TS PKT Queue</strong></p>
  
  <pre><code>/*
   * Test program for video decoder
   */
  
  #include &lt;stdio.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  
  extern "C" {
  
  #ifdef __cplusplus
      #define __STDC_CONSTANT_MACROS
      #ifdef _STDINT_H
          #undef _STDINT_H
      #endif
      #include &lt;stdint.h&gt;
  #endif
  }
  
  extern "C" {
  #include "libavcodec/avcodec.h"
  #include "libavformat/avformat.h"
  #include "libswscale/swscale.h"
  #include "libavutil/imgutils.h"
  #include "libavutil/opt.h"
  }
  
  
  class VideoDecoder
  {
  public:
      VideoDecoder();
      bool rcvTsPacket(AVPacket &amp;inTsPacket);
  
  private:
      AVCodec         *mpDecoder;
      AVCodecContext  *mpDecoderContext;
      AVFrame         *mpDecodedFrame;
      AVFormatContext *mpFmtContext;
  
  };
  
  VideoDecoder::VideoDecoder()
  {
      av_register_all();
  
      // FORMAT CONTEXT SETUP
      mpFmtContext = avformat_alloc_context();
      mpFmtContext-&gt;flags = AVFMT_NOFILE;
      // ????? WHAT ELSE ???? //
  
      // DECODER SETUP
      mpDecoder = avcodec_find_decoder(AV_CODEC_ID_H264);
      if (!mpDecoder)
      {
          printf("Could not load decoder\n");
          exit(11);
      }
  
      mpDecoderContext = avcodec_alloc_context3(NULL);
      if (avcodec_open2(mpDecoderContext, mpDecoder, NULL) &lt; 0)
      {
          printf("Cannot open decoder context\n");
          exit(1);
      }
  
      mpDecodedFrame = av_frame_alloc();
  }
  
  bool
  VideoDecoder::rcvTsPacket(AVPacket &amp;inTsPkt)
  {
      bool ret = true;
  
      if ((av_read_frame(mpFmtContext, &amp;inTsPkt)) &lt; 0)
      {
          printf("Error in av_read_frame()\n");
          ret = false;
      }
      else
      {
          // success.  Decode the TS packet
          int got;
          int len = avcodec_decode_video2(mpDecoderContext, mpDecodedFrame, &amp;got, &amp;inTsPkt);
          if (len &lt; 0)
              ret = false;
  
          if (got)
              printf("GOT A DECODED FRAME\n");
      }
  
      return ret;
  }
  
  int
  main(int argc, char **argv)
  {
      if (argc != 2)
      {
          printf("Usage: %s tsInFile\n", argv[0]);
          exit(1);
      }
  
      FILE *tsInFile = fopen(argv[1], "r");
      if (!tsInFile)
      {
          perror("Could not open TS input file");
          exit(2);
      }
  
      unsigned int tsPktNum = 0;
      uint8_t      tsBuffer[256];
      AVPacket     tsPkt;
      av_init_packet(&amp;tsPkt);
  
      VideoDecoder vDecoder;
  
      while (!feof(tsInFile))
      {
          tsPktNum++;
  
          tsPkt.size = 188;
          tsPkt.data = tsBuffer;
          fread(tsPkt.data, 188, 1, tsInFile);
  
          vDecoder.rcvTsPacket(tsPkt);
      }
  }
  </code></pre>