// Frame is fragmented.
// Process next RTP paks until have the entire frame.
// Paks will be in order in the queue, but maybe some missing?
// So if process pkt w/ Mbit set (last of fragm) and total < frameLength
// ignore pkt.
// Insert frame data only after got all fragments for the frame.
static int process_fragment (isma_enc_rtp_data_t *iptr,
                             rtp_packet *pak,
                             isma_frame_data_t *frame_data)
{
    uint16_t seq = pak->rtp_pak_seq;
    uint32_t ts = pak->rtp_pak_ts;
    isma_frag_data_t *cur = NULL;
    int read_mBit = 0;
    uint32_t total_len = 0;
    frame_data->is_fragment = 1;
    do {
        if (read_mBit == 1) {
            // get rid of frame_data - last frag seen but total length wrong
            cleanup_frag(iptr, frame_data);
            isma_message(LOG_ERR, ismaencrtp, "Error processing frag: early mBit");
            return (1);
        }
        if (pak == NULL) {
            cleanup_frag(iptr, frame_data);
            isma_message(LOG_ERR, ismaencrtp, "Error processing frag: not enough packets");
            return (1);
        }
        // check if ts and rtp seq numbers are ok, and lengths match
        if (ts != pak->rtp_pak_ts) {
            cleanup_frag(iptr, frame_data);
            isma_message(LOG_ERR, ismaencrtp,
                         "Error processing frag: wrong ts: ts= %x, pak->ts = %x",
                         ts, pak->rtp_pak_ts);
            return (1);
        }
        if (seq != pak->rtp_pak_seq) {
            cleanup_frag(iptr, frame_data);
            isma_message(LOG_ERR, ismaencrtp, "Error processing frag: wrong seq num");
            return (1);
        }
        // insert fragment info
        isma_frag_data_t *p = (isma_frag_data_t *)
                              malloc(sizeof(isma_frag_data_t));
        if (p == NULL) {
            isma_message(LOG_ERR, ismaencrtp, "Error processing frag: can't malloc");
            iptr->m_vft->free_pak(pak);
            return (1);
        }
        if (cur == NULL) {
            frame_data->frag_data = p;
            cur = p;
        } else {
            cur->frag_data_next = p;
            cur = p;
        }
        cur->frag_data_next = NULL;
        cur->pak = pak;
        // length in bits
        uint16_t header_len = ntohs(*(unsigned short *)pak->rtp_data);
        iptr->m_header_bitstream.init(&pak->rtp_data[sizeof(uint16_t)], header_len);
        // frag_ptr should just point to beginning of data in pkt
        uint32_t header_len_bytes = ((header_len + 7) / 8) + sizeof(uint16_t);
        cur->frag_ptr =  &pak->rtp_data[header_len_bytes];
        cur->frag_len = pak->rtp_data_len - header_len_bytes;
        // if aux data, move frag pointer
        if (iptr->m_fmtp->auxiliary_data_size_length > 0) {
            iptr->m_header_bitstream.byte_align();
            uint32_t aux_len;
            iptr->m_header_bitstream.getbits(iptr->m_fmtp->auxiliary_data_size_length, &aux_len);
            aux_len = (aux_len + 7) / 8;
            cur->frag_ptr += aux_len;
            cur->frag_len -= aux_len;
        }
        total_len += cur->frag_len;
#ifdef DEBUG_ISMA_RTP_FRAGS
        isma_message(LOG_DEBUG, ismaencrtp,
                     "rtp seq# %d, fraglen: %d, ts: %x",
                     pak->seq, cur->frag_len, pak->ts);
#endif
        seq = pak->rtp_pak_seq + 1;
        if (pak->rtp_pak_m)
            read_mBit = 1;
        iptr->m_vft->remove_from_list(iptr->m_ifptr, pak);
        pak = iptr->m_vft->get_next_pak(iptr->m_ifptr, NULL, 0);
    } while (total_len < frame_data->frame_len);

    // insert frame and return
    int error = insert_frame_data(iptr, frame_data);
    frame_data->last_in_pak = 1; // only one frame in pak
    // no need to remove pkt from queue, done at the end of do-while
    return (error);
}
static void process_packet_header (isma_enc_rtp_data_t *iptr)
{
    rtp_packet *pak;
    uint32_t frame_len;
    uint32_t prev_frame_len;
    uint32_t IV;
    uint32_t delta_IV;
    uint16_t header_len;
    uint32_t retvalue;

    pak = iptr->m_vft->get_next_pak(iptr->m_ifptr, NULL, 1);
    if (pak == NULL) {
        return;
    }

#ifdef DEBUG_ISMA_AAC
    isma_message(LOG_DEBUG, ismaencrtp,
                 "processing pak seq %d ts %x len %d",
                 pak->rtp_pak_seq, pak->rtp_pak_ts, pak->rtp_data_len);
#endif

    // This pak has not had it's header processed
    // length in bytes
    if (pak->rtp_data_len == 0) {
        iptr->m_vft->free_pak(pak);
        isma_message(LOG_ERR, ismaencrtp, "RTP audio packet with data length of 0");
        return;
    }

    header_len = ntohs(*(unsigned short *)pak->rtp_data);
    //fprintf(stdout, "----->AWV, process_packet_header header len %u\n", header_len);
    if (header_len < iptr->m_min_first_header_bits) {
        // bye bye, frame...
        iptr->m_vft->free_pak(pak);
        isma_message(LOG_ERR, ismaencrtp, "ISMA rtp - header len %d less than min %d",
                     header_len, iptr->m_min_first_header_bits);
        return;
    }

    iptr->m_header_bitstream.init(&pak->rtp_data[sizeof(uint16_t)],
                                  header_len);

    // this is the first frame in a packet so:
    // next should be 4 bytes of IV, what is retvalue if this returns??? awv
    if (iptr->m_header_bitstream.getbits(32, &IV) != 0)
        return;

    // what is retvalue here if this returns??? awv
    if (iptr->m_header_bitstream.getbits(iptr->m_fmtp->size_length, &frame_len) != 0)
        return;

    iptr->m_header_bitstream.getbits(iptr->m_fmtp->index_length, &retvalue);
    get_au_header_bits(iptr);
#ifdef DEBUG_ISMA_AAC
    uint64_t msec = iptr->m_vft->rtp_ts_to_msec(iptr->m_ifptr, pak->rtp_pak_ts,
                    pak->pd.rtp_pd_timestamp,
                    1);
    isma_message(LOG_DEBUG, ismaencrtp,
                 "1st - header len %u frame len %u ts %x U64",
                 header_len, frame_len, pak->rtp_pak_ts, msec);
#endif
    if (frame_len == 0) {
        iptr->m_vft->free_pak(pak);
        return;
    }
    uint8_t *frame_ptr;
    isma_frame_data_t *frame_data;
    uint32_t ts;
    ts = pak->rtp_pak_ts;
    frame_data = get_frame_data(iptr);
    frame_data->pak = pak;
    // frame pointer is after header_len + header_len size.  Header_len
    // is in bits - add 7, divide by 8 to get padding correctly.
    frame_data->frame_ptr = &pak->rtp_data[((header_len + 7) / 8)
                                           + sizeof(uint16_t)];
    prev_frame_len = frame_len;
    frame_data->frame_len = frame_len;
    frame_data->rtp_timestamp = ts;
    frame_data->IV = IV;
    //fprintf(stdout, "===>AWV A1, Len: %u  IV %u\n", frame_len, IV);

    // Check if frame is fragmented
    // frame_len plus the length of the 2 headers
    uint32_t frag_check = frame_len + sizeof(uint16_t);
    frag_check += iptr->m_fmtp->size_length / 8;
    if ((iptr->m_fmtp->size_length % 8) != 0) frag_check++;
    if (frag_check > pak->rtp_data_len) {
#ifdef DEBUG_ISMA_AAC
        isma_message(LOG_DEBUG, ismaencrtp, "Frame is fragmented");
#endif
        frame_data->is_fragment = 1;
        int err = process_fragment(iptr, pak, frame_data);
        if (err == 1)
            isma_message(LOG_ERR, ismaencrtp, "Error in processing the fragment");
        return;
    }
    else {
#ifdef DEBUG_ISMA_AAC
        isma_message(LOG_DEBUG, ismaencrtp, "Frame is not fragmented");
#endif
        frame_data->is_fragment = 0;
        frame_data->frag_data = NULL;
    }
    int error = insert_frame_data(iptr, frame_data);
    frame_ptr = frame_data->frame_ptr + frame_data->frame_len;
    while (iptr->m_header_bitstream.bits_remain() >= iptr->m_min_header_bits) {
        uint32_t stride;
        // if deltaIVLength is not zero, frames subsequent to the first frame
        // will have a deltaIV, otherwise nothing. in either case, need to
        // derive the IV.
        // next should be deltaIV, what is retvalue if this returns??? awv
        if (iptr->m_fmtp->ISMACrypIVDeltaLength == 2 ) {
            if (iptr->m_header_bitstream.getbits(16, &delta_IV) != 0)
                return;
            else {
                IV = IV + prev_frame_len + delta_IV;
            }
        }
        else {
            if (iptr->m_fmtp->ISMACrypIVDeltaLength == 1 ) {
                if (iptr->m_header_bitstream.getbits(8, &delta_IV) != 0)
                    return;
                else {
                    IV = IV + prev_frame_len + delta_IV;
                }
            }
            else {
                IV = IV + prev_frame_len;
            }
        }
        //fprintf(stdout, "=========>AWV, Delta IV %u   Delta IV len %d\n", deltaIV,
        //        iptr->m_fmtp->ISMACrypIVDeltaLength);

        iptr->m_header_bitstream.getbits(iptr->m_fmtp->size_length, &frame_len);
        iptr->m_header_bitstream.getbits(iptr->m_fmtp->index_delta_length, &stride);
        get_au_header_bits(iptr);
        ts += (iptr->m_rtp_ts_add * (1 + stride));
#ifdef DEBUG_ISMA_AAC
        msec = iptr->m_vft->rtp_ts_to_msec(iptr->m_ifptr,
                                           pak->rtp_pak_ts,
                                           pak->pd.rtp_pd_timestamp,
                                           1);
        isma_message(LOG_DEBUG, ismaencrtp,
                     "Stride %d len %d ts %x U64",
                     stride, frame_len, ts, msec);
#endif
        frame_data = get_frame_data(iptr);
        frame_data->pak = pak;
        frame_data->is_fragment = 0;
        frame_data->frag_data = NULL;
        frame_data->frame_ptr = frame_ptr;
        prev_frame_len = frame_len;
        frame_data->frame_len = frame_len;
        frame_ptr += frame_len;
        frame_data->IV = IV;
        frame_data->rtp_timestamp = ts;
        //fprintf(stdout, "===>AWV A2, Len: %u  IV %u\n", frame_len, IV);
        error |= insert_frame_data(iptr, frame_data);
    }
    if (error == 0 && frame_data != NULL) {
        frame_data->last_in_pak = 1;
    }
    else {
        isma_frame_data_t *p, *last = NULL;
        p = iptr->m_frame_data_head;
        while (p != NULL) {
            if (p->pak == pak) last = p;
            p = p->frame_data_next;
        }
        if (last != NULL) {
            last->last_in_pak = 1;
            isma_message(LOG_WARNING, ismaencrtp, "error at end - marked ts %x", last->rtp_timestamp);
        } else {
            // Didn't find pak in list.  Weird
            isma_message(LOG_ERR, ismaencrtp,
                         "Decoded packet with RTP timestamp %x and didn't"
                         "see any good frames", pak->rtp_pak_ts);
            iptr->m_vft->free_pak(pak);
            return;
        }
    }
    if (iptr->m_fmtp->auxiliary_data_size_length > 0) {
        iptr->m_header_bitstream.byte_align();
        uint32_t aux_len;
        iptr->m_header_bitstream.getbits(iptr->m_fmtp->auxiliary_data_size_length, &aux_len);
        aux_len = (aux_len + 7) / 8;
#ifdef DEBUG_ISMA_AAC
        isma_message(LOG_DEBUG, ismaencrtp, "Adding %d bytes for aux data size", aux_len);
#endif
        isma_frame_data_t *p;
        p = iptr->m_frame_data_head;
        while (p != NULL) {
            if (p->pak == pak) {
                p->frame_ptr += aux_len;
            }
            p = p->frame_data_next;
        }
    }
}
Esempio n. 3
0
static void process_packet_header (isma_rtp_data_t *iptr)
{
  rtp_packet *pak;
  uint32_t frame_len;
  uint16_t header_len;
  uint32_t retvalue;

  pak = iptr->m_vft->get_head_and_check(iptr->m_ifptr, false, 0);
  if (pak == NULL) {
    return;
  }
#ifdef DEBUG_ISMA_AAC
  isma_message(LOG_DEBUG, ismartp, 
	       "processing pak seq %d ts %x len %d", 
	       pak->rtp_pak_seq, pak->rtp_pak_ts, pak->rtp_data_len);
#endif
  // This pak has not had it's header processed
  // length in bytes
  if (pak->rtp_data_len == 0) {
    iptr->m_vft->free_pak(pak);
    isma_message(LOG_ERR, ismartp, "RTP audio packet with data length of 0");
    return;
  }

  header_len = ntohs(*(unsigned short *)pak->rtp_data);
  if (header_len < iptr->m_min_first_header_bits) {
    // bye bye, frame...
    iptr->m_vft->free_pak(pak);
    isma_message(LOG_ERR, ismartp, "ISMA rtp - header len %d less than min %d", 
		 header_len, iptr->m_min_first_header_bits);
    return;
  }

  iptr->m_header_bitstream.init(&pak->rtp_data[sizeof(uint16_t)],
			  header_len);
  if (iptr->m_header_bitstream.getbits(iptr->m_fmtp->size_length, &frame_len) != 0) 
    return;
  iptr->m_header_bitstream.getbits(iptr->m_fmtp->index_length, &retvalue);
  get_au_header_bits(iptr);
#ifdef DEBUG_ISMA_AAC
  uint64_t msec = iptr->m_vft->rtp_ts_to_msec(iptr->m_ifptr, pak->rtp_pak_ts, 
					      pak->pd.rtp_pd_timestamp,
					      1);
  isma_message(LOG_DEBUG, ismartp, 
	       "1st - header len %u frame len %u ts %x "U64, 
	       header_len, frame_len, pak->rtp_pak_ts, msec);
#endif
  if (frame_len == 0) {
    iptr->m_vft->free_pak(pak);
    return;
  }
  uint8_t *frame_ptr;
  isma_frame_data_t *frame_data;
  uint32_t ts;
  ts = pak->rtp_pak_ts;
  frame_data = get_frame_data(iptr);
  frame_data->pak = pak;
  // frame pointer is after header_len + header_len size.  Header_len
  // is in bits - add 7, divide by 8 to get padding correctly.
  frame_data->frame_ptr = &pak->rtp_data[((header_len + 7) / 8) 
				    + sizeof(uint16_t)];
  frame_data->frame_len = frame_len;
  frame_data->rtp_timestamp = ts;

  // Check if frame is fragmented
  // frame_len plus the length of the 2 headers
  uint32_t frag_check = frame_len + sizeof(uint16_t);
  frag_check += iptr->m_fmtp->size_length / 8;
  if ((iptr->m_fmtp->size_length % 8) != 0) frag_check++;
  if (frag_check > pak->rtp_data_len) {
#ifdef DEBUG_ISMA_AAC
    isma_message(LOG_DEBUG, ismartp, "Frame is fragmented");
#endif
    frame_data->is_fragment = 1;
    int err = process_fragment(iptr, pak, frame_data);
    if (err == 1)
      isma_message(LOG_ERR, ismartp, "Error in processing the fragment");
    return; 
  }
  else {
#ifdef DEBUG_ISMA_AAC
    isma_message(LOG_DEBUG, ismartp, "Frame is not fragmented");
#endif
    frame_data->is_fragment = 0;
    frame_data->frag_data = NULL;
  }
  int error = insert_frame_data(iptr, frame_data);
  frame_ptr = frame_data->frame_ptr + frame_data->frame_len;
  while (iptr->m_header_bitstream.bits_remain() >= iptr->m_min_header_bits) {
    uint32_t stride = 0;
    iptr->m_header_bitstream.getbits(iptr->m_fmtp->size_length, &frame_len);
    iptr->m_header_bitstream.getbits(iptr->m_fmtp->index_delta_length, &stride);
    get_au_header_bits(iptr);
    ts += (iptr->m_rtp_ts_add * (1 + stride));
#ifdef DEBUG_ISMA_AAC
    msec = iptr->m_vft->rtp_ts_to_msec(iptr->m_ifptr, 
				       pak->rtp_pak_ts, 
				       pak->pd.rtp_pd_timestamp,
				       1);
    isma_message(LOG_DEBUG, ismartp, 
		 "Stride %d len %d ts %x "U64,
		 stride, frame_len, ts, msec);
#endif
    frame_data = get_frame_data(iptr);
    frame_data->pak = pak;
    frame_data->is_fragment = 0;
    frame_data->frag_data = NULL;
    frame_data->frame_ptr = frame_ptr;
    frame_data->frame_len = frame_len;
    frame_ptr += frame_len;
    frame_data->rtp_timestamp = ts;
    error |= insert_frame_data(iptr, frame_data);
  }
  if (error == 0 && frame_data != NULL) { 
    frame_data->last_in_pak = 1;
  }
  else {
    isma_frame_data_t *p, *last = NULL;
    p = iptr->m_frame_data_head;
    while (p != NULL) {
      if (p->pak == pak) last = p;
      p = p->frame_data_next;
    }
    if (last != NULL) {
      last->last_in_pak = 1;
      isma_message(LOG_WARNING, ismartp, "error at end - marked ts %x", last->rtp_timestamp);
    } else {
      // Didn't find pak in list.  Weird
      isma_message(LOG_ERR, ismartp, 
		   "Decoded packet with RTP timestamp %x and didn't"
		   "see any good frames", pak->rtp_pak_ts);
      iptr->m_vft->free_pak(pak);
      return;
    }
  }
  if (iptr->m_fmtp->auxiliary_data_size_length > 0) {
    iptr->m_header_bitstream.byte_align();
    uint32_t aux_len = 0;
    iptr->m_header_bitstream.getbits(iptr->m_fmtp->auxiliary_data_size_length, &aux_len);
    aux_len = (aux_len + 7) / 8;
#ifdef DEBUG_ISMA_AAC
    isma_message(LOG_DEBUG, ismartp, "Adding %d bytes for aux data size", aux_len);
#endif
    isma_frame_data_t *p;
    p = iptr->m_frame_data_head;
    while (p != NULL) {
      if (p->pak == pak) {
	p->frame_ptr += aux_len;
      }
      p = p->frame_data_next;
    }
  }
}