static int hevc_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_hevc_ctx,

                              AVStream *st, AVPacket *pkt, uint32_t *timestamp,

                              const uint8_t *buf, int len, uint16_t seq,

                              int flags)

{

    const uint8_t *rtp_pl = buf;

    int tid, lid, nal_type;

    int first_fragment, last_fragment, fu_type;

    uint8_t new_nal_header[2];

    int res = 0;



    /* sanity check for size of input packet: 1 byte payload at least */

    if (len < RTP_HEVC_PAYLOAD_HEADER_SIZE + 1) {

        av_log(ctx, AV_LOG_ERROR, "Too short RTP/HEVC packet, got %d bytes\n", len);

        return AVERROR_INVALIDDATA;

    }



    /*

      decode the HEVC payload header according to section 4 of draft version 6:



         0                   1

         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5

        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

        |F|   Type    |  LayerId  | TID |

        +-------------+-----------------+



           Forbidden zero (F): 1 bit

           NAL unit type (Type): 6 bits

           NUH layer ID (LayerId): 6 bits

           NUH temporal ID plus 1 (TID): 3 bits

    */

    nal_type =  (buf[0] >> 1) & 0x3f;

    lid  = ((buf[0] << 5) & 0x20) | ((buf[1] >> 3) & 0x1f);

    tid  =   buf[1] & 0x07;



    /* sanity check for correct layer ID */

    if (lid) {

        /* future scalable or 3D video coding extensions */

        avpriv_report_missing_feature(ctx, "Multi-layer HEVC coding\n");

        return AVERROR_PATCHWELCOME;

    }



    /* sanity check for correct temporal ID */

    if (!tid) {

        av_log(ctx, AV_LOG_ERROR, "Illegal temporal ID in RTP/HEVC packet\n");

        return AVERROR_INVALIDDATA;

    }



    /* sanity check for correct NAL unit type */

    if (nal_type > 50) {

        av_log(ctx, AV_LOG_ERROR, "Unsupported (HEVC) NAL type (%d)\n", nal_type);

        return AVERROR_INVALIDDATA;

    }



    switch (nal_type) {

    /* aggregated packets (AP) */

    case 48:

        /* pass the HEVC payload header */

        buf += RTP_HEVC_PAYLOAD_HEADER_SIZE;

        len -= RTP_HEVC_PAYLOAD_HEADER_SIZE;



        /* pass the HEVC DONL field */

        if (rtp_hevc_ctx->using_donl_field) {

            buf += RTP_HEVC_DONL_FIELD_SIZE;

            len -= RTP_HEVC_DONL_FIELD_SIZE;

        }



        /* fall-through */

    /* video parameter set (VPS) */

    case 32:

    /* sequence parameter set (SPS) */

    case 33:

    /* picture parameter set (PPS) */

    case 34:

    /*  supplemental enhancement information (SEI) */

    case 39:

    /* single NAL unit packet */

    default:

        /* sanity check for size of input packet: 1 byte payload at least */

        if (len < 1) {

            av_log(ctx, AV_LOG_ERROR,

                   "Too short RTP/HEVC packet, got %d bytes of NAL unit type %d\n",

                   len, nal_type);

            return AVERROR_INVALIDDATA;

        }



        /* create A/V packet */

        if ((res = av_new_packet(pkt, sizeof(start_sequence) + len)) < 0)

            return res;

        /* A/V packet: copy start sequence */

        memcpy(pkt->data, start_sequence, sizeof(start_sequence));

        /* A/V packet: copy NAL unit data */

        memcpy(pkt->data + sizeof(start_sequence), buf, len);



        break;

    /* fragmentation unit (FU) */

    case 49:

        /* pass the HEVC payload header */

        buf += RTP_HEVC_PAYLOAD_HEADER_SIZE;

        len -= RTP_HEVC_PAYLOAD_HEADER_SIZE;



        if (len < 1)

            return AVERROR_INVALIDDATA;

        /*

             decode the FU header



              0 1 2 3 4 5 6 7

             +-+-+-+-+-+-+-+-+

             |S|E|  FuType   |

             +---------------+



                Start fragment (S): 1 bit

                End fragment (E): 1 bit

                FuType: 6 bits

        */

        first_fragment = buf[0] & 0x80;

        last_fragment  = buf[0] & 0x40;

        fu_type        = buf[0] & 0x3f;



        /* pass the HEVC FU header */

        buf += RTP_HEVC_FU_HEADER_SIZE;

        len -= RTP_HEVC_FU_HEADER_SIZE;



        /* pass the HEVC DONL field */

        if (rtp_hevc_ctx->using_donl_field) {

            buf += RTP_HEVC_DONL_FIELD_SIZE;

            len -= RTP_HEVC_DONL_FIELD_SIZE;

        }



        av_dlog(ctx, " FU type %d with %d bytes\n", fu_type, len);



        if (len > 0) {

            new_nal_header[0] = (rtp_pl[0] & 0x81) | (fu_type << 1);

            new_nal_header[1] = rtp_pl[1];



            /* start fragment vs. subsequent fragments */

            if (first_fragment) {

                if (!last_fragment) {

                    /* create A/V packet which is big enough */

                    if ((res = av_new_packet(pkt, sizeof(start_sequence) + sizeof(new_nal_header) + len)) < 0)

                        return res;

                    /* A/V packet: copy start sequence */

                    memcpy(pkt->data, start_sequence, sizeof(start_sequence));

                    /* A/V packet: copy new NAL header */

                    memcpy(pkt->data + sizeof(start_sequence), new_nal_header, sizeof(new_nal_header));

                    /* A/V packet: copy NAL unit data */

                    memcpy(pkt->data + sizeof(start_sequence) + sizeof(new_nal_header), buf, len);

                } else {

                    av_log(ctx, AV_LOG_ERROR, "Illegal combination of S and E bit in RTP/HEVC packet\n");

                    res = AVERROR_INVALIDDATA;

                }

            } else {

                /* create A/V packet */

                if ((res = av_new_packet(pkt, len)) < 0)

                    return res;

                /* A/V packet: copy NAL unit data */

                memcpy(pkt->data, buf, len);

            }

        } else {

            /* sanity check for size of input packet: 1 byte payload at least */

            av_log(ctx, AV_LOG_ERROR,

                   "Too short RTP/HEVC packet, got %d bytes of NAL unit type %d\n",

                   len, nal_type);

            res = AVERROR_INVALIDDATA;

        }



        break;

    /* PACI packet */

    case 50:

        /* Temporal scalability control information (TSCI) */

        avpriv_report_missing_feature(ctx, "PACI packets for RTP/HEVC\n");

        res = AVERROR_PATCHWELCOME;

        break;

    }



    pkt->stream_index = st->index;



    return res;

}
