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;
}
Beispiel #4
0
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;
}