func: static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
  
                                AVStream *st, AVPacket *pkt, uint32_t *timestamp,
  
                                const uint8_t *buf, int len, uint16_t seq,
  
                                int flags)
  
  {
  
      uint8_t nal;
  
      uint8_t type;
  
      int result = 0;
  
  
  
      if (!len) {
  
          av_log(ctx, AV_LOG_ERROR, "Empty H264 RTP packet\n");
  
          return AVERROR_INVALIDDATA;
  
      }
  
      nal  = buf[0];
  
      type = nal & 0x1f;
  
  
  
      assert(data);
  
      assert(buf);
  
  
  
      /* Simplify the case (these are all the nal types used internally by
  
       * the h264 codec). */
  
      if (type >= 1 && type <= 23)
  
          type = 1;
  
      switch (type) {
  
      case 0:                    // undefined, but pass them through
  
      case 1:
  
          av_new_packet(pkt, len + sizeof(start_sequence));
  
          memcpy(pkt->data, start_sequence, sizeof(start_sequence));
  
          memcpy(pkt->data + sizeof(start_sequence), buf, len);
  
          COUNT_NAL_TYPE(data, nal);
  
          break;
  
  
  
      case 24:                   // STAP-A (one packet, multiple nals)
  
          // consume the STAP-A NAL
  
          buf++;
  
          len--;
  
          // first we are going to figure out the total size
  
          {
  
              int pass         = 0;
  
              int total_length = 0;
  
              uint8_t *dst     = NULL;
  
  
  
              for (pass = 0; pass < 2; pass++) {
  
                  const uint8_t *src = buf;
  
                  int src_len        = len;
  
  
  
                  while (src_len > 2) {
  
                      uint16_t nal_size = AV_RB16(src);
  
  
  
                      // consume the length of the aggregate
  
                      src     += 2;
  
                      src_len -= 2;
  
  
  
                      if (nal_size <= src_len) {
  
                          if (pass == 0) {
  
                              // counting
  
                              total_length += sizeof(start_sequence) + nal_size;
  
                          } else {
  
                              // copying
  
                              assert(dst);
  
                              memcpy(dst, start_sequence, sizeof(start_sequence));
  
                              dst += sizeof(start_sequence);
  
                              memcpy(dst, src, nal_size);
  
                              COUNT_NAL_TYPE(data, *src);
  
                              dst += nal_size;
  
                          }
  
                      } else {
  
                          av_log(ctx, AV_LOG_ERROR,
  
                                 "nal size exceeds length: %d %d\n", nal_size, src_len);
  
                      }
  
  
  
                      // eat what we handled
  
                      src     += nal_size;
  
                      src_len -= nal_size;
  
  
  
                      if (src_len < 0)
  
                          av_log(ctx, AV_LOG_ERROR,
  
                                 "Consumed more bytes than we got! (%d)\n", src_len);
  
                  }
  
  
  
                  if (pass == 0) {
  
                      /* now we know the total size of the packet (with the
  
                       * start sequences added) */
  
                      av_new_packet(pkt, total_length);
  
                      dst = pkt->data;
  
                  } else {
  
                      assert(dst - pkt->data == total_length);
  
                  }
  
              }
  
          }
  
          break;
  
  
  
      case 25:                   // STAP-B
  
      case 26:                   // MTAP-16
  
      case 27:                   // MTAP-24
  
      case 29:                   // FU-B
  
          av_log(ctx, AV_LOG_ERROR,
  
                 "Unhandled type (%d) (See RFC for implementation details\n",
  
                 type);
  
          result = AVERROR(ENOSYS);
  
          break;
  
  
  
      case 28:                   // FU-A (fragmented nal)
  
          buf++;
  
          len--;                 // skip the fu_indicator
  
          if (len > 1) {
  
              // these are the same as above, we just redo them here for clarity
  
              uint8_t fu_indicator      = nal;
  
              uint8_t fu_header         = *buf;
  
              uint8_t start_bit         = fu_header >> 7;
  
              uint8_t av_unused end_bit = (fu_header & 0x40) >> 6;
  
              uint8_t nal_type          = fu_header & 0x1f;
  
              uint8_t reconstructed_nal;
  
  
  
              // Reconstruct this packet's true nal; only the data follows.
  
              /* The original nal forbidden bit and NRI are stored in this
  
               * packet's nal. */
  
              reconstructed_nal  = fu_indicator & 0xe0;
  
              reconstructed_nal |= nal_type;
  
  
  
              // skip the fu_header
  
              buf++;
  
              len--;
  
  
  
              if (start_bit)
  
                  COUNT_NAL_TYPE(data, nal_type);
  
              if (start_bit) {
  
                  /* copy in the start sequence, and the reconstructed nal */
  
                  av_new_packet(pkt, sizeof(start_sequence) + sizeof(nal) + len);
  
                  memcpy(pkt->data, start_sequence, sizeof(start_sequence));
  
                  pkt->data[sizeof(start_sequence)] = reconstructed_nal;
  
                  memcpy(pkt->data + sizeof(start_sequence) + sizeof(nal), buf, len);
  
              } else {
  
                  av_new_packet(pkt, len);
  
                  memcpy(pkt->data, buf, len);
  
              }
  
          } else {
  
              av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H264 RTP packet\n");
  
              result = AVERROR_INVALIDDATA;
  
          }
  
          break;
  
  
  
      case 30:                   // undefined
  
      case 31:                   // undefined
  
      default:
  
          av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)\n", type);
  
          result = AVERROR_INVALIDDATA;
  
          break;
  
      }
  
  
  
      pkt->stream_index = st->index;
  
  
  
      return result;
  
  }
  