天天看點

分享一段H264視訊和AAC音頻的RTP封包代碼

1. H264視訊的RTP封包

static int h264_parse(Track *tr, uint8_t *data, size_t len) 

    h264_priv *priv = tr->private_data; 

//    double nal_time; // see page 9 and 7.4.1.2 

    size_t nalsize = 0, index = 0; 

    uint8_t *p, *q; 

    if (priv->is_avc) { 

        while (1) { 

            unsigned int i; 

            if(index >= len) break; 

            //get the nal size 

            nalsize = 0; 

            for(i = 0; i < priv->nal_length_size; i++) 

                nalsize = (nalsize << 8) | data[index++]; 

            if(nalsize <= 1 || nalsize > len) { 

                if(nalsize == 1) { 

                    index++; 

                    continue; 

                } else { 

                    fnc_log(FNC_LOG_VERBOSE, "[h264] AVC: nal size %d", nalsize); 

                    break; 

                } 

            } 

            if (DEFAULT_MTU >= nalsize) { 

                mparser_buffer_write(tr, 

                                     tr->properties.pts, 

                                     tr->properties.dts, 

                                     tr->properties.frame_duration, 

                                     1, 

                                     data + index, nalsize); 

                fnc_log(FNC_LOG_VERBOSE, "[h264] single NAL"); 

            } else { 

            // single NAL, to be fragmented, FU-A; 

                frag_fu_a(data + index, nalsize, DEFAULT_MTU, tr); 

            index += nalsize; 

        } 

    } else { 

        //seek to the first startcode 

        for (p = data; p<data + len - 3; p++) { 

            if (p[0] == 0 && p[1] == 0 && p[2] == 1) { 

                break; 

        if (p >= data + len) return ERR_PARSE; 

        //seek to the next startcode [0 0 1] 

            for (q = p; q<data+len-3;q++) { 

                if (q[0] == 0 && q[1] == 0 && q[2] == 1) { 

            if (q >= data + len) break; 

            if (DEFAULT_MTU >= q - p) { 

                fnc_log(FNC_LOG_VERBOSE, "[h264] Sending NAL %d",p[0]&0x1f); 

                                     p, q - p); 

                //FU-A 

                fnc_log(FNC_LOG_VERBOSE, "[h264] frags"); 

                frag_fu_a(p, q - p, DEFAULT_MTU, tr); 

            p = q; 

        // last NAL 

        fnc_log(FNC_LOG_VERBOSE, "[h264] last NAL %d",p[0]&0x1f); 

        if (DEFAULT_MTU >= len - (p - data)) { 

            fnc_log(FNC_LOG_VERBOSE, "[h264] no frags"); 

            mparser_buffer_write(tr, 

                                 tr->properties.pts, 

                                 tr->properties.dts, 

                                 tr->properties.frame_duration, 

                                 1, 

                                 p, len - (p - data)); 

        } else { 

            //FU-A 

            fnc_log(FNC_LOG_VERBOSE, "[h264] frags"); 

            frag_fu_a(p, len - (p - data), DEFAULT_MTU, tr); 

    } 

    fnc_log(FNC_LOG_VERBOSE, "[h264] Frame completed"); 

    return ERR_NOERROR; 

static int h264_parse(Track *tr, uint8_t *data, size_t len)  

{  

    h264_priv *priv = tr->private_data;  

//    double nal_time; // see page 9 and 7.4.1.2  

    size_t nalsize = 0, index = 0;  

    uint8_t *p, *q;  

    if (priv->is_avc) {  

        while (1) {  

            unsigned int i;  

            if(index >= len) break;  

            //get the nal size  

            nalsize = 0;  

            for(i = 0; i < priv->nal_length_size; i++)  

                nalsize = (nalsize << 8) | data[index++];  

            if(nalsize <= 1 || nalsize > len) {  

                if(nalsize == 1) {  

                    index++;  

                    continue;  

                } else {  

                    fnc_log(FNC_LOG_VERBOSE, "[h264] AVC: nal size %d", nalsize);  

                    break;  

                }  

            }  

            if (DEFAULT_MTU >= nalsize) {  

                mparser_buffer_write(tr,  

                                     tr->properties.pts,  

                                     tr->properties.dts,  

                                     tr->properties.frame_duration,  

                                     1,  

                                     data + index, nalsize);  

                fnc_log(FNC_LOG_VERBOSE, "[h264] single NAL");  

            } else {  

            // single NAL, to be fragmented, FU-A;  

                frag_fu_a(data + index, nalsize, DEFAULT_MTU, tr);  

            index += nalsize;  

        }  

    } else {  

        //seek to the first startcode  

        for (p = data; p<data + len - 3; p++) {  

            if (p[0] == 0 && p[1] == 0 && p[2] == 1) {  

                break;  

        if (p >= data + len) return ERR_PARSE;  

        //seek to the next startcode [0 0 1]  

            for (q = p; q<data+len-3;q++) {  

                if (q[0] == 0 && q[1] == 0 && q[2] == 1) {  

            if (q >= data + len) break;  

            if (DEFAULT_MTU >= q - p) {  

                fnc_log(FNC_LOG_VERBOSE, "[h264] Sending NAL %d",p[0]&0x1f);  

                                     p, q - p);  

                //FU-A  

                fnc_log(FNC_LOG_VERBOSE, "[h264] frags");  

                frag_fu_a(p, q - p, DEFAULT_MTU, tr);  

            p = q;  

        // last NAL  

        fnc_log(FNC_LOG_VERBOSE, "[h264] last NAL %d",p[0]&0x1f);  

        if (DEFAULT_MTU >= len - (p - data)) {  

            fnc_log(FNC_LOG_VERBOSE, "[h264] no frags");  

            mparser_buffer_write(tr,  

                                 tr->properties.pts,  

                                 tr->properties.dts,  

                                 tr->properties.frame_duration,  

                                 1,  

                                 p, len - (p - data));  

        } else {  

            //FU-A  

            fnc_log(FNC_LOG_VERBOSE, "[h264] frags");  

            frag_fu_a(p, len - (p - data), DEFAULT_MTU, tr);  

    }  

    fnc_log(FNC_LOG_VERBOSE, "[h264] Frame completed");  

    return ERR_NOERROR;  

}  

2. AAC的RTP封包

static int aac_parse(Track *tr, uint8_t *data, size_t len) 

    //XXX handle the last packet on EOF 

    int off = 0; 

    uint32_t payload = DEFAULT_MTU - AU_HEADER_SIZE; 

    uint8_t *packet = g_malloc0(DEFAULT_MTU); 

    if(!packet) return ERR_ALLOC; 

// trim away extradata 

//    data += AAC_EXTRA; 

//    len -= AAC_EXTRA; 

    packet[0] = 0x00; 

    packet[1] = 0x10; 

    packet[2] = (len & 0x1fe0) >> 5; 

    packet[3] = (len & 0x1f) << 3; 

    if (len > payload) { 

        while (len > payload) { 

            memcpy(packet + AU_HEADER_SIZE, data + off, payload); 

                                 0, 

                                 packet, DEFAULT_MTU); 

            len -= payload; 

            off += payload; 

    memcpy(packet + AU_HEADER_SIZE, data + off, len); 

    mparser_buffer_write(tr, 

                         tr->properties.pts, 

                         tr->properties.dts, 

                         tr->properties.frame_duration, 

                         1, 

                         packet, len + AU_HEADER_SIZE); 

    g_free(packet); 

static int aac_parse(Track *tr, uint8_t *data, size_t len)  

    //XXX handle the last packet on EOF  

    int off = 0;  

    uint32_t payload = DEFAULT_MTU - AU_HEADER_SIZE;  

    uint8_t *packet = g_malloc0(DEFAULT_MTU);  

    if(!packet) return ERR_ALLOC;  

// trim away extradata  

//    data += AAC_EXTRA;  

//    len -= AAC_EXTRA;  

    packet[0] = 0x00;  

    packet[1] = 0x10;  

    packet[2] = (len & 0x1fe0) >> 5;  

    packet[3] = (len & 0x1f) << 3;  

    if (len > payload) {  

        while (len > payload) {  

            memcpy(packet + AU_HEADER_SIZE, data + off, payload);  

                                 0,  

                                 packet, DEFAULT_MTU);  

            len -= payload;  

            off += payload;  

    memcpy(packet + AU_HEADER_SIZE, data + off, len);  

    mparser_buffer_write(tr,  

                         tr->properties.pts,  

                         tr->properties.dts,  

                         tr->properties.frame_duration,  

                         1,  

                         packet, len + AU_HEADER_SIZE);  

    g_free(packet);  

上面的變量 AU_HEADER_SIZE=4

/* au header

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

      |     AU-size                           |

      |     AU-Index / AU-Index-delta         |

      |     CTS-flag                          |

      |     CTS-delta                         |

      |     DTS-flag                          |

      |     DTS-delta                         |

      |     RAP-flag                          |

      |     Stream-state                      |

*/

繼續閱讀