static int control(sh_audio_t *sh,int cmd,void* arg, ...) { int start, len; switch(cmd) { case ADCTRL_RESYNC_STREAM: if(mpa_sync(sh, 1, &len, NULL, NULL, NULL, NULL, NULL) >= 0) return CONTROL_TRUE; else return CONTROL_FALSE; case ADCTRL_SKIP_FRAME: start = mpa_sync(sh, 2, &len, NULL, NULL, NULL, NULL, NULL); if(len < 0) return CONTROL_FALSE; sh->a_in_buffer_len -= start; memmove(sh->a_in_buffer, &(sh->a_in_buffer[start]), sh->a_in_buffer_len); return CONTROL_TRUE; } return CONTROL_UNKNOWN; }
static int init(sh_audio_t *sh) { int cnt, chans, srate, spf, mpa_layer, br, len; if((cnt = mpa_sync(sh, 1, &len, &chans, &srate, &spf, &mpa_layer, &br)) < 0) return 0; sh->channels = chans; sh->samplerate = srate; sh->i_bps = br * 125; sh->samplesize = 2; mp_msg(MSGT_DECAUDIO,MSGL_V,"AC_HWMPA initialized, bitrate: %d kb/s\r\n", len); return 1; }
static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen) { int len, start, tot; int chans, srate, spf, mpa_layer, br; int tot2; tot = tot2 = 0; while(tot2 < maxlen) { start = mpa_sync(sh, 1, &len, &chans, &srate, &spf, &mpa_layer, &br); if(start < 0 || tot2 + spf * 2 * chans > maxlen) break; if(start + len > sh->a_in_buffer_len) { int l; l = FFMIN(sh->a_in_buffer_size - sh->a_in_buffer_len, start + len); l = demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len], l); if(! l) break; sh->a_in_buffer_len += l; continue; } memcpy(&buf[tot], &(sh->a_in_buffer[start]), len); tot += len; sh->a_in_buffer_len -= start + len; memmove(sh->a_in_buffer, &(sh->a_in_buffer[start + len]), sh->a_in_buffer_len); tot2 += spf * 2 * chans; /* HACK: seems to fix most A/V sync issues */ break; } memset(&buf[tot], 0, tot2-tot); return tot2; }
static int mpa_parse(rtp_ssrc * stm_src, rtp_frame * fr, rtp_buff * config) { rtp_mpa *mpa_priv; rtp_pkt *pkt; size_t pkt_len; // size of RTP packet, rtp header included. mpa_frm mpa; uint8_t *mpa_data; if (!fr) return RTP_IN_PRM_ERR; mpa_priv = stm_src->privs[fr->pt]; // XXX should we check if payload/mime-type are compatible with parser? if (!(pkt = rtp_get_pkt(stm_src, &pkt_len))) return RTP_BUFF_EMPTY; // discard pkt if it's fragmented and the first fragment was lost while (RTP_MPA_PKT(pkt)->frag_offset) { rtp_rm_pkt(stm_src); if (!(pkt = rtp_get_pkt(stm_src, &pkt_len))) return RTP_BUFF_EMPTY; else if (RTP_PKT_PT(pkt) != fr->pt) return RTP_PARSE_ERROR; } mpa_data = RTP_MPA_PKT(pkt)->data; nms_printf(NMSML_DBG3, "--- fr->len: %d-%d\n", pkt_len, RTP_PAYLOAD_SIZE(pkt, pkt_len)); pkt_len = RTP_MPA_DATA_LEN(pkt, pkt_len); // now pkt_len is only the payload len (excluded mpa subheader) nms_printf(NMSML_DBG3, "--- fr->len: %d\n", pkt_len); if (mpa_sync(&mpa_data, &pkt_len)) return RTP_PARSE_ERROR; if (mpa_decode_header(mpa_data, &mpa)) return RTP_PARSE_ERROR; /* XXX if the frame is not fragmented we could use directly the data contained in bufferpool * instead of memcpy the frame in a newly allocated space */ // init private struct if this is the first time we're called if (!mpa_priv) { nms_printf(NMSML_DBG3, "[rtp_mpa] allocating new private struct..."); if (! (stm_src->privs[fr->pt] = mpa_priv = malloc(sizeof(rtp_mpa)))) return RTP_ERRALLOC; mpa_priv->data_size = max(DEFAULT_MPA_DATA_FRAME, mpa.frm_len); if (!(mpa_priv->data = malloc(mpa_priv->data_size))) return RTP_ERRALLOC; nms_printf(NMSML_DBG3, "done\n"); } else if ((RTP_MPA_FRAG_OFFSET(pkt) + pkt_len) > mpa_priv->data_size) { nms_printf(NMSML_DBG3, "[rtp_mpa] reallocating data..."); mpa_priv->data_size += max(DEFAULT_MPA_DATA_FRAME, pkt_len); if (!(mpa_priv->data = realloc(mpa_priv->data, mpa_priv->data_size))) return RTP_ERRALLOC; nms_printf(NMSML_DBG3, "done\n"); } fr->data = mpa_priv->data; for (fr->len = 0; pkt && (fr->len < mpa.frm_len) && (fr->timestamp == RTP_PKT_TS(pkt)); fr->len += pkt_len, rtp_rm_pkt(stm_src), (pkt = rtp_get_pkt(stm_src, &pkt_len)), pkt_len = RTP_MPA_DATA_LEN(pkt, pkt_len)) { // pkt consistency checks if (RTP_MPA_FRAG_OFFSET(pkt) + pkt_len <= mpa_priv->data_size) { nms_printf(NMSML_DBG3, "copying %d byte of data to offset: %d\n", pkt_len, RTP_MPA_FRAG_OFFSET(pkt)); memcpy(fr->data + RTP_MPA_FRAG_OFFSET(pkt), mpa_data, pkt_len); } } nms_printf(NMSML_DBG3, "fr->len: %d\n", fr->len); return RTP_FILL_OK; }