示例#1
0
文件: tospdif.c 项目: IAPark/vlc
static void set_16( filter_t *p_filter, void *p_buf, uint16_t i_val )
{
    if( p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFB )
        SetWBE( p_buf, i_val );
    else
        SetWLE( p_buf, i_val );
}
示例#2
0
/*****************************************************************************
 * DoWork: convert a buffer
 *****************************************************************************/
static block_t *DoWork( filter_t * p_filter, block_t *p_in_buf )
{
    /* AC3 is natively big endian. Most SPDIF devices have the native
     * endianness of the computer system.
     * On Mac OS X however, little endian devices are also common.
     */
    static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
    static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x01 };
    uint16_t i_frame_size = p_in_buf->i_buffer / 2;
    uint8_t * p_in = p_in_buf->p_buffer;

    block_t *p_out_buf = filter_NewAudioBuffer( p_filter, AOUT_SPDIF_SIZE );
    if( !p_out_buf )
        goto out;
    uint8_t * p_out = p_out_buf->p_buffer;

    /* Copy the S/PDIF headers. */
    if( p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFB )
    {
        vlc_memcpy( p_out, p_sync_be, 6 );
        p_out[4] = p_in[5] & 0x7; /* bsmod */
        SetWBE( p_out + 6, i_frame_size << 4 );
        vlc_memcpy( &p_out[8], p_in, i_frame_size * 2 );
    }
    else
    {
        vlc_memcpy( p_out, p_sync_le, 6 );
        p_out[5] = p_in[5] & 0x7; /* bsmod */
        SetWLE( p_out + 6, i_frame_size << 4 );
        swab( p_in, &p_out[8], i_frame_size * 2 );
    }
    vlc_memset( p_out + 8 + i_frame_size * 2, 0,
                AOUT_SPDIF_SIZE - i_frame_size * 2 - 8 );

    p_out_buf->i_dts = p_in_buf->i_dts;
    p_out_buf->i_pts = p_in_buf->i_pts;
    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_buffer = AOUT_SPDIF_SIZE;
out:
    block_Release( p_in_buf );
    return p_out_buf;
}
示例#3
0
void xiph_decode (demux_t *demux, void *data, block_t *block)
{
    rtp_xiph_t *self = (rtp_xiph_t *)data;			// sunqueen modify

    if (!data || block->i_buffer < 4)
        goto drop;

    /* 32-bits RTP header (§2.2) */
    uint32_t ident = GetDWBE (block->p_buffer);
    block->i_buffer -= 4;
    block->p_buffer += 4;

    unsigned fragtype = (ident >> 6) & 3;
    unsigned datatype = (ident >> 4) & 3;
    unsigned pkts = (ident) & 15;
    ident >>= 8;

    /* RTP defragmentation */
    if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY))
    {   /* Screwed! discontinuity within a fragmented packet */
        msg_Warn (demux, self->vorbis ?
                  "discontinuity in fragmented Vorbis packet" :
                  "discontinuity in fragmented Theora packet");
        block_Release (self->block);
        self->block = NULL;
    }

    if (fragtype <= 1)
    {
        if (self->block) /* Invalid first fragment */
        {
            block_Release (self->block);
            self->block = NULL;
        }
    }
    else
    {
        if (!self->block)
            goto drop; /* Invalid non-first fragment */
    }

    if (fragtype > 0)
    {   /* Fragment */
        if (pkts > 0 || block->i_buffer < 2)
            goto drop;

        size_t fraglen = GetWBE (block->p_buffer);
        if (block->i_buffer < (fraglen + 2))
            goto drop; /* Invalid payload length */
        block->i_buffer = fraglen;
        if (fragtype == 1)/* Keep first fragment */
        {
            block->i_buffer += 2;
            self->block = block;
        }
        else
        {   /* Append non-first fragment */
            size_t len = self->block->i_buffer;
            self->block = block_Realloc (self->block, 0, len + fraglen);
            if (!self->block)
            {
                block_Release (block);
                return;
            }
            memcpy (self->block->p_buffer + len, block->p_buffer + 2,
                    fraglen);
            block_Release (block);
        }
        if (fragtype < 3)
            return; /* Non-last fragment */

        /* Last fragment reached, process it */
        block = self->block;
        self->block = NULL;
        SetWBE (block->p_buffer, block->i_buffer - 2);
        pkts = 1;
    }

    /* RTP payload packets processing */
    while (pkts > 0)
    {
        if (block->i_buffer < 2)
            goto drop;

        size_t len = GetWBE (block->p_buffer);
        block->i_buffer -= 2;
        block->p_buffer += 2;
        if (block->i_buffer < len)
            goto drop;

        switch (datatype)
        {
            case 0: /* Raw payload */
            {
                if (self->ident != ident)
                {
                    msg_Warn (demux, self->vorbis ?
                        "ignoring raw Vorbis payload without configuration" :
                        "ignoring raw Theora payload without configuration");
                    break;
                }
                block_t *raw = block_Alloc (len);
                memcpy (raw->p_buffer, block->p_buffer, len);
                raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */
                codec_decode (demux, self->id, raw);
                break;
            }

            case 1: /* Packed configuration frame (§3.1.1) */
            {
                if (self->ident == ident)
                    break; /* Ignore config retransmission */

                void *extv;
                ssize_t extc = xiph_header (&extv, block->p_buffer, len);
                if (extc < 0)
                    break;

                es_format_t fmt;
                es_format_Init (&fmt, self->vorbis ? AUDIO_ES : VIDEO_ES,
                                self->vorbis ? VLC_CODEC_VORBIS
                                             : VLC_CODEC_THEORA);
                fmt.p_extra = extv;
                fmt.i_extra = extc;
                codec_destroy (demux, self->id);
                msg_Dbg (demux, self->vorbis ?
                         "Vorbis packed configuration received (%06"PRIx32")" :
                         "Theora packed configuration received (%06"PRIx32")",
                         ident);
                self->ident = ident;
                self->id = (es_out_id_t *)codec_init (demux, &fmt);			// sunqueen modify
                break;
            }
        }

        block->i_buffer -= len;
        block->p_buffer += len;
        pkts--;
    }

drop:
    block_Release (block);
}
示例#4
0
文件: sap.c 项目: Devil399/vlc
/**
 *  Registers a new session with the announce handler, using a pregenerated SDP
 *
 * \param obj a VLC object
 * \param sdp the SDP to register
 * \param dst session address (needed for SAP address auto detection)
 * \return the new session descriptor structure
 */
session_descriptor_t *
sout_AnnounceRegisterSDP (vlc_object_t *obj, const char *sdp,
                          const char *dst)
{
    int i;
    char psz_addr[NI_MAXNUMERICHOST];
    union
    {
        struct sockaddr     a;
        struct sockaddr_in  in;
        struct sockaddr_in6 in6;
    } addr;
    socklen_t addrlen = 0;
    struct addrinfo *res;

    msg_Dbg (obj, "adding SAP session");

    if (vlc_getaddrinfo (dst, 0, NULL, &res) == 0)
    {
        if (res->ai_addrlen <= sizeof (addr))
            memcpy (&addr, res->ai_addr, res->ai_addrlen);
        addrlen = res->ai_addrlen;
        freeaddrinfo (res);
    }

    if (addrlen == 0 || addrlen > sizeof (addr))
    {
        msg_Err (obj, "No/invalid address specified for SAP announce" );
        return NULL;
    }

    /* Determine SAP multicast address automatically */
    switch (addr.a.sa_family)
    {
#if defined (HAVE_INET_PTON) || defined (_WIN32)
        case AF_INET6:
        {
            /* See RFC3513 for list of valid IPv6 scopes */
            struct in6_addr *a6 = &addr.in6.sin6_addr;

            memcpy( a6->s6_addr + 2, "\x00\x00\x00\x00\x00\x00"
                   "\x00\x00\x00\x00\x00\x02\x7f\xfe", 14 );
            if( IN6_IS_ADDR_MULTICAST( a6 ) )
                /* force flags to zero, preserve scope */
                a6->s6_addr[1] &= 0xf;
            else
                /* Unicast IPv6 - assume global scope */
                memcpy( a6->s6_addr, "\xff\x0e", 2 );
            break;
        }
#endif

        case AF_INET:
        {
            /* See RFC2365 for IPv4 scopes */
            uint32_t ipv4 = addr.in.sin_addr.s_addr;

            /* 224.0.0.0/24 => 224.0.0.255 */
            if ((ipv4 & htonl (0xffffff00)) == htonl (0xe0000000))
                ipv4 =  htonl (0xe00000ff);
            else
            /* 239.255.0.0/16 => 239.255.255.255 */
            if ((ipv4 & htonl (0xffff0000)) == htonl (0xefff0000))
                ipv4 =  htonl (0xefffffff);
            else
            /* 239.192.0.0/14 => 239.195.255.255 */
            if ((ipv4 & htonl (0xfffc0000)) == htonl (0xefc00000))
                ipv4 =  htonl (0xefc3ffff);
            else
            if ((ipv4 & htonl (0xff000000)) == htonl (0xef000000))
                ipv4 = 0;
            else
            /* other addresses => 224.2.127.254 */
                ipv4 = htonl (0xe0027ffe);

            if( ipv4 == 0 )
            {
                msg_Err (obj, "Out-of-scope multicast address "
                         "not supported by SAP");
                return NULL;
            }

            addr.in.sin_addr.s_addr = ipv4;
            break;
        }

        default:
            msg_Err (obj, "Address family %d not supported by SAP",
                     addr.a.sa_family);
            return NULL;
    }

    i = vlc_getnameinfo( &addr.a, addrlen,
                         psz_addr, sizeof( psz_addr ), NULL, NI_NUMERICHOST );

    if( i )
    {
        msg_Err (obj, "%s", gai_strerror (i));
        return NULL;
    }

    /* Find/create SAP address thread */
    sap_address_t *sap_addr;

    msg_Dbg (obj, "using SAP address: %s", psz_addr);
    vlc_mutex_lock (&sap_mutex);
    for (sap_addr = sap_addrs; sap_addr; sap_addr = sap_addr->next)
        if (!strcmp (psz_addr, sap_addr->group))
            break;

    if (sap_addr == NULL)
    {
        sap_addr = AddressCreate (obj, psz_addr);
        if (sap_addr == NULL)
        {
            vlc_mutex_unlock (&sap_mutex);
            return NULL;
        }
        sap_addr->next = sap_addrs;
        sap_addrs = sap_addr;
    }
    /* Switch locks.
     * NEVER take the global SAP lock when holding a SAP thread lock! */
    vlc_mutex_lock (&sap_addr->lock);
    vlc_mutex_unlock (&sap_mutex);

    size_t length = 20;
    switch (sap_addr->orig.ss_family)
    {
#ifdef AF_INET6
        case AF_INET6:
            length += 16;
            break;
#endif
        case AF_INET:
            length += 4;
            break;
        default:
            assert (0);
    }

    /* XXX: Check for dupes */
    length += strlen (sdp);

    session_descriptor_t *session = malloc (sizeof (*session) + length);
    if (unlikely(session == NULL))
    {
        vlc_mutex_unlock (&sap_addr->lock);
        return NULL; /* NOTE: we should destroy the thread if left unused */
    }
    session->next = sap_addr->first;
    sap_addr->first = session;
    session->length = length;

    /* Build the SAP Headers */
    uint8_t *buf = session->data;

    /* SAPv1, not encrypted, not compressed */
    buf[0] = 0x20;
    buf[1] = 0x00; /* No authentication length */
    SetWBE(buf + 2, mdate()); /* ID hash */

    size_t offset = 4;
    switch (sap_addr->orig.ss_family)
    {
#ifdef AF_INET6
        case AF_INET6:
        {
            const struct in6_addr *a6 =
                &((const struct sockaddr_in6 *)&sap_addr->orig)->sin6_addr;
            memcpy (buf + offset, a6, 16);
            buf[0] |= 0x10; /* IPv6 flag */
            offset += 16;
            break;
        }
#endif
        case AF_INET:
        {
            const struct in_addr *a4 =
                &((const struct sockaddr_in *)&sap_addr->orig)->sin_addr;
            memcpy (buf + offset, a4, 4);
            offset += 4;
            break;
        }

    }

    memcpy (buf + offset, "application/sdp", 16);
    offset += 16;

    /* Build the final message */
    strcpy((char *)buf + offset, sdp);

    sap_addr->session_count++;
    vlc_cond_signal (&sap_addr->wait);
    vlc_mutex_unlock (&sap_addr->lock);
    return session;
}
示例#5
0
文件: dtstospdif.c 项目: Mettbrot/vlc
/*****************************************************************************
 * DoWork: convert a buffer
 *****************************************************************************/
static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf )
{
    uint32_t i_ac5_spdif_type = 0;
    uint16_t i_fz = p_in_buf->i_nb_samples * 4;
    uint16_t i_frame, i_length = p_in_buf->i_buffer;
    static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x00, 0x00 };
    static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x00 };

    if( p_in_buf->i_buffer != p_filter->p_sys->i_frame_size )
    {
        /* Frame size changed, reset everything */
        msg_Warn( p_filter, "Frame size changed from %zu to %zu, "
                          "resetting everything.",
                  p_filter->p_sys->i_frame_size, p_in_buf->i_buffer );

        p_filter->p_sys->i_frame_size = p_in_buf->i_buffer;
        p_filter->p_sys->p_buf = xrealloc( p_filter->p_sys->p_buf,
                                                  p_in_buf->i_buffer * 3 );
        p_filter->p_sys->i_frames = 0;
    }

    /* Backup frame */
    /* TODO: keeping the blocks in a list would save one memcpy */
    memcpy( p_filter->p_sys->p_buf + p_in_buf->i_buffer *
                  p_filter->p_sys->i_frames,
                p_in_buf->p_buffer, p_in_buf->i_buffer );

    p_filter->p_sys->i_frames++;

    if( p_filter->p_sys->i_frames < 3 )
    {
        if( p_filter->p_sys->i_frames == 1 )
            /* We'll need the starting date */
            p_filter->p_sys->start_date = p_in_buf->i_pts;

        /* Not enough data */
        block_Release( p_in_buf );
        return NULL;
    }

    p_filter->p_sys->i_frames = 0;
    block_t *p_out_buf = filter_NewAudioBuffer( p_filter,
                                                12 * p_in_buf->i_nb_samples );
    if( !p_out_buf )
        goto out;

    for( i_frame = 0; i_frame < 3; i_frame++ )
    {
        uint16_t i_length_padded = i_length;
        uint8_t * p_out = p_out_buf->p_buffer + (i_frame * i_fz);
        uint8_t * p_in = p_filter->p_sys->p_buf + (i_frame * i_length);

        switch( p_in_buf->i_nb_samples )
        {
            case  512: i_ac5_spdif_type = 0x0B; break;
            case 1024: i_ac5_spdif_type = 0x0C; break;
            case 2048: i_ac5_spdif_type = 0x0D; break;
        }

        /* Copy the S/PDIF headers. */
        if( p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFB )
        {
            memcpy( p_out, p_sync_be, 6 );
            p_out[5] = i_ac5_spdif_type;
            SetWBE( p_out + 6, i_length << 3 );
        }
        else
        {
            memcpy( p_out, p_sync_le, 6 );
            p_out[4] = i_ac5_spdif_type;
            SetWLE( p_out + 6, i_length << 3 );
        }

        if( ( (p_in[0] == 0x1F || p_in[0] == 0x7F) && p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFL ) ||
            ( (p_in[0] == 0xFF || p_in[0] == 0xFE) && p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFB ) )
        {
            /* We are dealing with a big endian bitstream and a little endian output
             * or a little endian bitstream and a big endian output.
             * Byteswap the stream */
            swab( p_in, p_out + 8, i_length );

            /* If i_length is odd, we have to adjust swapping a bit.. */
            if( i_length & 1 )
            {
                p_out[8+i_length-1] = 0;
                p_out[8+i_length] = p_in[i_length-1];
                i_length_padded++;
            }
        }
        else
        {
            memcpy( p_out + 8, p_in, i_length );
        }

        if( i_fz > i_length + 8 )
        {
            memset( p_out + 8 + i_length_padded, 0,
                        i_fz - i_length_padded - 8 );
        }
    }

    p_out_buf->i_pts = p_filter->p_sys->start_date;
    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples * 3;
    p_out_buf->i_buffer = p_out_buf->i_nb_samples * 4;
out:
    block_Release( p_in_buf );
    return p_out_buf;
}