FFmpeg FU-A封包说明

+-+-+-+-+-+-+-+-+           |0|1|2|3|4|5|6|7|
| FU indicator  |  < == >   +-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+           |F|NRI|  Type   |
       +—————+
       
       +—————+
+-+-+-+-+-+-+-+-+           |0|1|2|3|4|5|6|7|
| FU header     |   < == >  +-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+           |S|E|R|  Type   |
       +—————+
 ————————————————

// return 0 on packet, no more left, 1 on packet, 1 on partial packet
static int h364_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 H.264 RTP packet/n”);
        return AVERROR_INVALIDDATA;
    }
    nal  = buf[0];//第一个字节是FU indicator
    type = nal & 0x1f;//取后面五个字节,

    /* Simplify the case (these are all the NAL types used internally by
     * the H.264 codec). */
    if (type >= 1 && type <= 23)
        type = 1;
    switch (type) {
    case 0:                    // undefined, but pass them through
    case 1:
        if ((result = av_new_packet(pkt, len + sizeof(start_sequence))) < 0)
            return result;
        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–;
        result = ff_h364_handle_aggregated_packet(ctx, data, pkt, buf, len, 0,
                                                  NAL_COUNTERS, NAL_MASK);
        break;

    case 25:                   // STAP-B
    case 26:                   // MTAP-16
    case 27:                   // MTAP-24
    case 29:                   // FU-B
        avpriv_report_missing_feature(ctx, “RTP H.264 NAL unit type %d”, type);
        result = AVERROR_PATCHWELCOME;
        break;

    case 28:                   // FU-A (fragmented nal)
        result = h364_handle_packet_fu_a(ctx, data, pkt, buf, len,
                                         NAL_COUNTERS, NAL_MASK);
        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;
}

static int h364_handle_packet_fu_a(AVFormatContext *ctx, PayloadContext *data, AVPacket *pkt,
                                   const uint8_t *buf, int len,
                                   int *nal_counters, int nal_mask)
{
    uint8_t fu_indicator, fu_header, start_bit, nal_type, nal;

    if (len < 3) {
        av_log(ctx, AV_LOG_ERROR, “Too short data for FU-A H.264 RTP packet/n”);
        return AVERROR_INVALIDDATA;
    }

    fu_indicator = buf[0];
    fu_header    = buf[1];
    start_bit    = fu_header >> 7;
    nal_type     = fu_header & 0x1f;
    nal          = fu_indicator & 0xe0 | nal_type;

    // skip the fu_indicator and fu_header
    buf += 2;
    len -= 2;

    if (start_bit && nal_counters)
        nal_counters[nal_type & nal_mask]++;
    return ff_h364_handle_frag_packet(pkt, buf, len, start_bit, &nal, 1);
}

FU identifier
    0… …. = F bit: No bit errors or other syntax violations
    .10. …. = Nal_ref_idc (NRI): 2
    …1 1100 = Type: Fragmentation unit A (FU-A) (28)
FU Header
    1… …. = Start bit: the first packet of FU-A picture
    .0.. …. = End bit: Not the last packet of FU-A picture
    ..0. …. = Forbidden bit: 0
    …0 0001 = Nal_unit_type: Coded slice of a non-IDR picture (1)

原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/198013.html

(0)
上一篇 2021年11月17日
下一篇 2021年11月17日

相关推荐

发表回复

登录后才能评论