static int insert_frame_data (isma_enc_rtp_data_t *iptr, isma_frame_data_t *frame_data) { SDL_LockMutex(iptr->m_rtp_packet_mutex); if (iptr->m_frame_data_head == NULL) { iptr->m_frame_data_head = frame_data; } else { int32_t diff; isma_frame_data_t *p, *q; q = NULL; p = iptr->m_frame_data_head; do { diff = frame_data->rtp_timestamp - p->rtp_timestamp; if (diff == 0) { isma_message(LOG_ERR, ismaencrtp, "Duplicate timestamp of %x found in RTP packet", frame_data->rtp_timestamp); isma_message(LOG_DEBUG, ismaencrtp, "Seq number orig %d new %d", p->pak->rtp_pak_seq, frame_data->pak->rtp_pak_seq); // if fragmented frame, free all frag_data if (frame_data->is_fragment == 1) { isma_frag_data_t * p = NULL; while ((p = frame_data->frag_data) != NULL) { frame_data->frag_data = p->frag_data_next; CHECK_AND_FREE(p); } } // put frame_data on free list frame_data->frame_data_next = iptr->m_frame_data_free; iptr->m_frame_data_free = frame_data; SDL_UnlockMutex(iptr->m_rtp_packet_mutex); return 1; } else if (diff < 0) { if (q == NULL) { frame_data->frame_data_next = iptr->m_frame_data_head; iptr->m_frame_data_head = frame_data; } else { q->frame_data_next = frame_data; frame_data->frame_data_next = p; } SDL_UnlockMutex(iptr->m_rtp_packet_mutex); return 0; } q = p; p = p->frame_data_next; } while (p != NULL); // insert at end; q->frame_data_next = frame_data; } SDL_UnlockMutex(iptr->m_rtp_packet_mutex); return 0; }
static void flush_rtp_packets (rtp_plugin_data_t *pifptr) { isma_enc_rtp_data_t *iptr = (isma_enc_rtp_data_t *)pifptr; isma_frame_data_t *p; SDL_LockMutex(iptr->m_rtp_packet_mutex); if (iptr->m_frame_data_on != NULL) { iptr->m_frame_data_on->frame_data_next = iptr->m_frame_data_head; iptr->m_frame_data_head = iptr->m_frame_data_on; iptr->m_frame_data_on = NULL; } if (iptr->m_frame_data_head != NULL) { p = iptr->m_frame_data_head; while (p->frame_data_next != NULL) { #ifdef DEBUG_ISMA_AAC isma_message(LOG_DEBUG, ismaencrtp, "reset removing pak %d", p->pak->rtp_pak_seq); #endif if (p->last_in_pak != 0) { if (p->is_fragment == 1) { // get rid of frag data isma_frag_data_t * q = NULL; while ((q = p->frag_data) != NULL) { p->frag_data = q->frag_data_next; CHECK_AND_FREE(q); } } iptr->m_vft->free_pak(p->pak); } p = p->frame_data_next; } p->frame_data_next = iptr->m_frame_data_free; iptr->m_frame_data_free = iptr->m_frame_data_head; iptr->m_frame_data_head = NULL; } SDL_UnlockMutex(iptr->m_rtp_packet_mutex); }
/* * Isma rtp bytestream has a potential set of headers at the beginning * of each rtp frame. This can interleave frames in different packets */ rtp_plugin_data_t *isma_rtp_plugin_create (format_list_t *media_fmt, uint8_t rtp_payload_type, rtp_vft_t *vft, void *ifptr) { isma_enc_rtp_data_t *iptr; fmtp_parse_t *fmtp; iptr = MALLOC_STRUCTURE(isma_enc_rtp_data_t); if ( iptr == NULL ) return NULL; memset(iptr, 0, sizeof(isma_enc_rtp_data_t)); if (strcasecmp(media_fmt->media->media, "audio") == 0) { ismacrypInitSession(&(iptr->myEncSID), KeyTypeAudio); } iptr->m_vft = vft; iptr->m_ifptr = ifptr; iptr->m_rtp_packet_mutex = SDL_CreateMutex(); #ifdef ISMA_RTP_DUMP_OUTPUT_TO_FILE iptr->m_outfile = fopen("isma.aac", "w"); #endif iptr->m_frame_data_head = NULL; iptr->m_frame_data_on = NULL; iptr->m_frame_data_free = NULL; isma_frame_data_t *p; for (iptr->m_frame_data_max = 0; iptr->m_frame_data_max < 25; iptr->m_frame_data_max++) { p = (isma_frame_data_t *)malloc(sizeof(isma_frame_data_t)); p->frame_data_next = iptr->m_frame_data_free; iptr->m_frame_data_free = p; } fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param, iptr->m_vft->log_msg); mpeg4_audio_config_t audio_config; decode_mpeg4_audio_config(fmtp->config_binary, fmtp->config_binary_len, &audio_config); if (audio_object_type_is_aac(&audio_config)) { iptr->m_rtp_ts_add = audio_config.codec.aac.frame_len_1024 != 0 ? 1024 : 960; } else { iptr->m_rtp_ts_add = audio_config.codec.celp.samples_per_frame; isma_message(LOG_DEBUG, ismaencrtp, "celp spf is %d", iptr->m_rtp_ts_add); } iptr->m_rtp_ts_add = (iptr->m_rtp_ts_add * media_fmt->rtpmap->clock_rate) / audio_config.frequency; isma_message(LOG_DEBUG, ismaencrtp, "Rtp ts add is %d (%d %d)", iptr->m_rtp_ts_add, media_fmt->rtpmap->clock_rate, audio_config.frequency); iptr->m_fmtp = fmtp; iptr->m_min_first_header_bits = iptr->m_fmtp->size_length + iptr->m_fmtp->index_length; iptr->m_min_header_bits = iptr->m_fmtp->size_length + iptr->m_fmtp->index_delta_length; if (iptr->m_fmtp->CTS_delta_length > 0) { iptr->m_min_header_bits++; iptr->m_min_first_header_bits++; } if (iptr->m_fmtp->DTS_delta_length > 0) { iptr->m_min_header_bits++; iptr->m_min_first_header_bits++; } isma_message(LOG_DEBUG, ismaencrtp, "min headers are %d %d", iptr->m_min_first_header_bits, iptr->m_min_header_bits); iptr->m_min_header_bits += iptr->m_fmtp->auxiliary_data_size_length; iptr->m_min_first_header_bits += iptr->m_fmtp->auxiliary_data_size_length; iptr->m_frag_reass_buffer = NULL; iptr->m_frag_reass_size_max = 0; return (&iptr->plug); }
static bool start_next_frame (rtp_plugin_data_t *pifptr, uint8_t **buffer, uint32_t *buflen, frame_timestamp_t *ts, void **userdata) { isma_enc_rtp_data_t *iptr = (isma_enc_rtp_data_t *)pifptr; uint64_t timetick; if (iptr->m_frame_data_on != NULL) { uint32_t next_ts; #ifdef DEBUG_ISMA_AAC isma_message(LOG_DEBUG, ismaencrtp, "Advancing to next pak data - old ts %x", iptr->m_frame_data_on->rtp_timestamp); #endif if (iptr->m_frame_data_on->last_in_pak != 0) { // We're done with all the data in this packet - get rid // of the rtp packet. if (iptr->m_frame_data_on->is_fragment == 1) { // if fragmented, need to get rid of all paks pointed to isma_frag_data_t *q = iptr->m_frame_data_on->frag_data; while (q != NULL) { rtp_packet *pak = q->pak; q->pak = NULL; if (pak != NULL) { iptr->m_vft->free_pak(pak); } q = q->frag_data_next; #ifdef DEBUG_ISMA_AAC isma_message(LOG_DEBUG, ismaencrtp, "removing pak - frag %d", pak->rtp_pak_seq); #endif } } else { rtp_packet *pak = iptr->m_frame_data_on->pak; iptr->m_frame_data_on->pak = NULL; iptr->m_vft->free_pak(pak); #ifdef DEBUG_ISMA_AAC isma_message(LOG_DEBUG, ismaencrtp, "removing pak %d", pak->rtp_pak_seq); #endif } } /* * Remove the frame data head pointer, and put it on the free list */ isma_frame_data_t *p = NULL; SDL_LockMutex(iptr->m_rtp_packet_mutex); p = iptr->m_frame_data_on; iptr->m_frame_data_on = NULL; next_ts = p->rtp_timestamp; p->frame_data_next = iptr->m_frame_data_free; iptr->m_frame_data_free = p; // free all frag_data for this frame if (p->is_fragment == 1) { isma_frag_data_t * q = p->frag_data; while (q != NULL) { p->frag_data = q->frag_data_next; CHECK_AND_FREE(q); q = p->frag_data; } } SDL_UnlockMutex(iptr->m_rtp_packet_mutex); /* * Now, look for the next timestamp - process a bunch of new * rtp packets, if we have to... */ next_ts += iptr->m_rtp_ts_add; if (iptr->m_frame_data_head == NULL || iptr->m_frame_data_head->rtp_timestamp != next_ts) { // process next pak in list. Process until next timestamp is found, // or 500 msec worth of data is found (in which case, go with first) do { process_packet_header(iptr); } while (iptr->m_vft->get_next_pak(iptr->m_ifptr, NULL, 0) != NULL && ((iptr->m_frame_data_head == NULL) || (iptr->m_frame_data_head->rtp_timestamp != next_ts)) && (iptr->m_frame_data_free != NULL)); } #ifdef DEBUG_ISMA_AAC else { // iptr->m_frame_data_head is correct isma_message(LOG_DEBUG, ismaencrtp, "frame_data_head is correct"); } #endif } else { // first time. Process a bunch of packets, go with first one... // asdf - will want to eventually add code to drop the first couple // of packets if they're not consecutive. do { process_packet_header(iptr); } while (iptr->m_frame_data_free != NULL); } /* * Init up the offsets */ if (iptr->m_frame_data_head != NULL) { SDL_LockMutex(iptr->m_rtp_packet_mutex); iptr->m_frame_data_on = iptr->m_frame_data_head; iptr->m_frame_data_head = iptr->m_frame_data_head->frame_data_next; SDL_UnlockMutex(iptr->m_rtp_packet_mutex); if (iptr->m_frame_data_on->is_fragment == 1) { iptr->m_frag_reass_size = 0; isma_frag_data_t *ptr; ptr = iptr->m_frame_data_on->frag_data; while (ptr != NULL) { if (iptr->m_frag_reass_size + ptr->frag_len > iptr->m_frag_reass_size_max) { iptr->m_frag_reass_size_max += MAX(4096, ptr->frag_len); iptr->m_frag_reass_buffer = (uint8_t *)realloc(iptr->m_frag_reass_buffer, iptr->m_frag_reass_size_max); } memmove(iptr->m_frag_reass_buffer + iptr->m_frag_reass_size, ptr->frag_ptr, ptr->frag_len); iptr->m_frag_reass_size += ptr->frag_len; ptr = ptr->frag_data_next; } *buffer = iptr->m_frag_reass_buffer; *buflen = iptr->m_frag_reass_size; } else { *buffer = iptr->m_frame_data_on->frame_ptr; *buflen = iptr->m_frame_data_on->frame_len; } } else { *buffer = NULL; } #ifdef ISMA_RTP_DUMP_OUTPUT_TO_FILE if (*buffer != NULL) { fwrite(*buffer, *buflen, 1, iptr->m_outfile); } #endif timetick = iptr->m_vft->rtp_ts_to_msec(iptr->m_ifptr, iptr->m_frame_data_on != NULL ? iptr->m_frame_data_on->rtp_timestamp : iptr->m_ts, iptr->m_frame_data_on ? iptr->m_frame_data_on->pak->pd.rtp_pd_timestamp : 0, 0); if (iptr->m_frame_data_on != NULL) iptr->m_ts = iptr->m_frame_data_on->rtp_timestamp; // We're going to have to handle wrap better... #ifdef DEBUG_ISMA_AAC isma_message(LOG_DEBUG, ismaencrtp, "start next frame %p %d ts "LLX" "LLU, *buffer, *buflen, iptr->m_ts, timetick); #endif ismacrypDecryptSampleRandomAccess(iptr->myEncSID, iptr->m_frame_data_on->IV, *buflen, *buffer); ts->audio_freq_timestamp = iptr->m_ts; ts->msec_timestamp = timetick; ts->timestamp_is_pts = true; return (true); }
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; } } }
// 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_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; } } }