예제 #1
0
static int PeekBlock(stream_t *s, rar_block_t *hdr)
{
    const uint8_t *peek;
    int peek_size = stream_Peek(s, &peek, 11);

    if (peek_size < 7)
        return VLC_EGENERIC;

    hdr->crc   = GetWLE(&peek[0]);
    hdr->type  = peek[2];
    hdr->flags = GetWLE(&peek[3]);
    hdr->size  = GetWLE(&peek[5]);
    hdr->add_size = 0;
    if ((hdr->flags & 0x8000) ||
        hdr->type == RAR_BLOCK_FILE ||
        hdr->type == RAR_BLOCK_SUBBLOCK) {
        if (peek_size < 11)
            return VLC_EGENERIC;
        hdr->add_size = GetDWLE(&peek[7]);
    }

    if (hdr->size < 7)
        return VLC_EGENERIC;
    return VLC_SUCCESS;
}
예제 #2
0
/****************************************************************************
 *
 * Basics functions to manipulates chunks
 *
 ****************************************************************************/
static int AVI_ChunkReadCommon( stream_t *s, avi_chunk_t *p_chk )
{
    const uint8_t *p_peek;
    int i_peek;

    memset( p_chk, 0, sizeof( avi_chunk_t ) );

    if( ( i_peek = stream_Peek( s, &p_peek, 8 ) ) < 8 )
    {
        return VLC_EGENERIC;
    }

    p_chk->common.i_chunk_fourcc = GetFOURCC( p_peek );
    p_chk->common.i_chunk_size   = GetDWLE( p_peek + 4 );
    p_chk->common.i_chunk_pos    = stream_Tell( s );

    p_chk->common.p_father = NULL;
    p_chk->common.p_next = NULL;
    p_chk->common.p_first = NULL;
    p_chk->common.p_next = NULL;

#ifdef AVI_DEBUG
    msg_Dbg( (vlc_object_t*)s,
             "found Chunk fourcc:%8.8x (%4.4s) size:%"PRId64" pos:%"PRId64,
             p_chk->common.i_chunk_fourcc,
             (char*)&p_chk->common.i_chunk_fourcc,
             p_chk->common.i_chunk_size,
             p_chk->common.i_chunk_pos );
#endif
    return VLC_SUCCESS;
}
예제 #3
0
파일: wav.c 프로젝트: Tilka/vlc
/*****************************************************************************
 * Local functions
 *****************************************************************************/
static int ChunkFind( demux_t *p_demux, const char *fcc, unsigned int *pi_size )
{
    const uint8_t *p_peek;

    for( ;; )
    {
        uint32_t i_size;

        if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
        {
            msg_Err( p_demux, "cannot peek" );
            return VLC_EGENERIC;
        }

        i_size = GetDWLE( p_peek + 4 );

        msg_Dbg( p_demux, "chunk: fcc=`%4.4s` size=%"PRIu32, p_peek, i_size );

        if( !memcmp( p_peek, fcc, 4 ) )
        {
            if( pi_size )
            {
                *pi_size = i_size;
            }
            return VLC_SUCCESS;
        }

        /* Skip chunk */
        if( stream_Read( p_demux->s, NULL, 8 ) != 8 ||
                stream_Read( p_demux->s, NULL, i_size ) != (int)i_size ||
                ( (i_size & 1) && stream_Read( p_demux->s, NULL, 1 ) != 1 ) )
            return VLC_EGENERIC;
    }
}
예제 #4
0
파일: oggspots.c 프로젝트: videolan/vlc
/*****************************************************************************
 * DecodePacket: decodes an OggSpots packet.
 *****************************************************************************/
static picture_t* DecodePacket(decoder_t* p_dec, block_t* p_block)
{
    decoder_sys_t* p_sys = p_dec->p_sys;
    uint32_t i_img_offset;
    picture_t* p_pic;

    if (p_block->i_buffer < 20) {
        msg_Dbg(p_dec, "Packet too short");
        goto error;
    }

    /* Byte offset */
    i_img_offset = GetDWLE(p_block->p_buffer);
    if (i_img_offset < 20) {
        msg_Dbg(p_dec, "Invalid byte offset");
        goto error;
    }

    /* Image format */
    if ( !memcmp(&p_block->p_buffer[4], "PNG", 3) ) {
        p_dec->fmt_in.video.i_chroma = VLC_CODEC_PNG;
    }
    else if ( !memcmp(&p_block->p_buffer[4], "JPEG", 4) ) {
        p_dec->fmt_in.video.i_chroma = VLC_CODEC_JPEG;
    }
    else {
        char psz_image_type[8+1];
        strncpy(psz_image_type, (char*)&p_block->p_buffer[4], 8);
        psz_image_type[sizeof(psz_image_type)-1] = '\0';

        msg_Dbg(p_dec, "Unsupported image format: %s", psz_image_type);
        goto error;
    }

    /* We currently ignore the rest of the header and let the image format
     * handle the details */

    p_block->i_buffer -= i_img_offset;
    p_block->p_buffer += i_img_offset;

    p_pic = image_Read(p_sys->p_image, p_block,
                       &p_dec->fmt_in,
                       &p_dec->fmt_out.video);
    if (p_pic == NULL) {
        return NULL;
    }

    p_pic->b_force = true;
    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
    decoder_UpdateVideoFormat(p_dec);

    return p_pic;

error:
    block_Release(p_block);
    return NULL;
}
예제 #5
0
파일: araw.c 프로젝트: chouquette/vlc
static void U32LDecode( void *outp, const uint8_t *in, unsigned samples )
{
    uint32_t *out = outp;

    for( size_t i = 0; i < samples; i++ )
    {
        *(out++) = GetDWLE( in ) - 0x80000000;
        in += 4;
    }
}
예제 #6
0
파일: id3tag.c 프로젝트: FLYKingdom/vlc
static size_t GetAPEvXSize( const uint8_t *p_data, int i_data )
{
    uint32_t flags;
    size_t i_body;

    if( i_data < APE_TAG_HEADERSIZE ||
        ( GetDWLE( &p_data[8] ) != 1000 && GetDWLE( &p_data[8] ) != 2000 ) || /* v1/v2 only */
        strncmp( (char*)p_data, "APETAGEX", 8 ) ||
        GetDWLE( &p_data[8+4+4] ) <= 0 )
        return 0;

    i_body = GetDWLE( &p_data[8+4] );
    flags = GetDWLE( &p_data[8+4+4] );

    /* is it the header */
    if( flags & (1<<29) )
        return i_body + ( (flags&(1<<30)) ? APE_TAG_HEADERSIZE : 0 );

    /* it is the footer */
    return i_body + ( (flags&(1<<31)) ? APE_TAG_HEADERSIZE : 0 );
}
예제 #7
0
파일: opus_header.c 프로젝트: 0xheart0/vlc
static int comment_add(char **comments, size_t *length, const char *tag,
                       const char *val)
{
    char *p = *comments;
    int vendor_length = GetDWLE(p + 8);
    size_t user_comment_list_length = GetDWLE(p + 8 + 4 + vendor_length);
    size_t tag_len = (tag ? strlen(tag) : 0);
    size_t val_len = strlen(val);
    size_t len = (*length) + 4 + tag_len + val_len;

    p = realloc(p, len);
    if (p == NULL)
        return 1;

    SetDWLE(p + *length, tag_len + val_len);          /* length of comment */
    if (tag) memcpy(p + *length + 4, tag, tag_len);         /* comment */
    memcpy(p + *length + 4 + tag_len, val, val_len);        /* comment */
    SetDWLE(p + 8 + 4 + vendor_length, user_comment_list_length + 1);
    *comments = p;
    *length = len;
    return 0;
}
예제 #8
0
파일: araw.c 프로젝트: chouquette/vlc
static void S32IDecode( void *outp, const uint8_t *in, unsigned samples )
{
    int32_t *out = outp;

    for( size_t i = 0; i < samples; i++ )
    {
#ifdef WORDS_BIGENDIAN
        *(out++) = GetDWLE( in );
#else
        *(out++) = GetDWBE( in );
#endif
        in += 4;
    }
}
예제 #9
0
파일: image.c 프로젝트: jomanmuk/vlc-2.2
static bool IsBmp(stream_t *s)
{
    const uint8_t *header;
    if (stream_Peek(s, &header, 18) < 18)
        return false;
    if (memcmp(header, "BM", 2) &&
        memcmp(header, "BA", 2) &&
        memcmp(header, "CI", 2) &&
        memcmp(header, "CP", 2) &&
        memcmp(header, "IC", 2) &&
        memcmp(header, "PT", 2))
        return false;
    uint32_t file_size   = GetDWLE(&header[2]);
    uint32_t data_offset = GetDWLE(&header[10]);
    uint32_t header_size = GetDWLE(&header[14]);
    if (file_size != 14 && file_size != 14 + header_size &&
        file_size <= data_offset)
        return false;
    if (data_offset < header_size + 14)
        return false;
    if (header_size != 12 && header_size < 40)
        return false;
    return true;
}
static void F32IDecode( void *outp, const uint8_t *in, unsigned samples )
{
    float *out = outp;

    for( size_t i = 0; i < samples; i++ )
    {
        union { float f; uint32_t u; } s;

#ifdef WORDS_BIGENDIAN
        s.u = GetDWLE( in );
#else
        s.u = GetDWBE( in );
#endif
        *(out++) = s.f;
        in += 4;
    }
}
예제 #11
0
파일: wav.c 프로젝트: Tilka/vlc
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    const uint8_t *p_peek;
    unsigned int   i_size;
    unsigned int   i_extended;
    const char    *psz_name;

    WAVEFORMATEXTENSIBLE *p_wf_ext = NULL;
    WAVEFORMATEX         *p_wf = NULL;

    /* Is it a wav file ? */
    if( stream_Peek( p_demux->s, &p_peek, 12 ) < 12 )
        return VLC_EGENERIC;

    if( memcmp( p_peek, "RIFF", 4 ) || memcmp( &p_peek[8], "WAVE", 4 ) )
    {
        return VLC_EGENERIC;
    }

    p_demux->pf_demux     = Demux;
    p_demux->pf_control   = Control;
    p_demux->p_sys        = p_sys = malloc( sizeof( *p_sys ) );
    if( unlikely(!p_sys) )
        return VLC_ENOMEM;

    p_sys->p_es           = NULL;
    p_sys->i_chans_to_reorder = 0;
    p_sys->i_channel_mask = 0;

    /* skip riff header */
    if( stream_Read( p_demux->s, NULL, 12 ) != 12 )
        goto error;

    /* search fmt chunk */
    if( ChunkFind( p_demux, "fmt ", &i_size ) )
    {
        msg_Err( p_demux, "cannot find 'fmt ' chunk" );
        goto error;
    }
    i_size += 2;
    if( i_size < sizeof( WAVEFORMATEX ) )
    {
        msg_Err( p_demux, "invalid 'fmt ' chunk" );
        goto error;
    }
    if( stream_Read( p_demux->s, NULL, 8 ) != 8 )
        goto error;


    /* load waveformatex */
    p_wf_ext = malloc( i_size );
    if( unlikely( !p_wf_ext ) )
        goto error;

    p_wf         = &p_wf_ext->Format;
    p_wf->cbSize = 0;
    i_size      -= 2;
    if( stream_Read( p_demux->s, p_wf, i_size ) != (int)i_size ||
            ( ( i_size & 1 ) && stream_Read( p_demux->s, NULL, 1 ) != 1 ) )
    {
        msg_Err( p_demux, "cannot load 'fmt ' chunk" );
        goto error;
    }

    es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
    wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &p_sys->fmt.i_codec,
                      &psz_name );
    p_sys->fmt.audio.i_channels      = GetWLE ( &p_wf->nChannels );
    p_sys->fmt.audio.i_rate          = GetDWLE( &p_wf->nSamplesPerSec );
    p_sys->fmt.audio.i_blockalign    = GetWLE( &p_wf->nBlockAlign );
    p_sys->fmt.i_bitrate             = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8;
    p_sys->fmt.audio.i_bitspersample = GetWLE( &p_wf->wBitsPerSample );
    if( i_size >= sizeof(WAVEFORMATEX) )
        p_sys->fmt.i_extra = __MIN( GetWLE( &p_wf->cbSize ), i_size - sizeof(WAVEFORMATEX) );
    i_extended = 0;

    /* Handle new WAVE_FORMAT_EXTENSIBLE wav files */
    /* see the following link for more information:
     * http://www.microsoft.com/whdc/device/audio/multichaud.mspx#EFAA */
    if( GetWLE( &p_wf->wFormatTag ) == WAVE_FORMAT_EXTENSIBLE &&
            i_size >= sizeof( WAVEFORMATEXTENSIBLE ) &&
            ( p_sys->fmt.i_extra + sizeof( WAVEFORMATEX )
              >= sizeof( WAVEFORMATEXTENSIBLE ) ) )
    {
        unsigned i_channel_mask;
        GUID guid_subformat;

        guid_subformat = p_wf_ext->SubFormat;
        guid_subformat.Data1 = GetDWLE( &p_wf_ext->SubFormat.Data1 );
        guid_subformat.Data2 = GetWLE( &p_wf_ext->SubFormat.Data2 );
        guid_subformat.Data3 = GetWLE( &p_wf_ext->SubFormat.Data3 );

        sf_tag_to_fourcc( &guid_subformat, &p_sys->fmt.i_codec, &psz_name );

        i_extended = sizeof( WAVEFORMATEXTENSIBLE ) - sizeof( WAVEFORMATEX );
        p_sys->fmt.i_extra -= i_extended;

        i_channel_mask = GetDWLE( &p_wf_ext->dwChannelMask );
        if( i_channel_mask )
        {
            int i_match = 0;
            for( unsigned i = 0; i < sizeof(pi_channels_src)/sizeof(*pi_channels_src); i++ )
            {
                if( i_channel_mask & pi_channels_src[i] )
                {
                    if( !( p_sys->i_channel_mask & pi_channels_in[i] ) )
                        i_match++;

                    i_channel_mask &= ~pi_channels_src[i];
                    p_sys->i_channel_mask |= pi_channels_in[i];

                    if( i_match >= p_sys->fmt.audio.i_channels )
                        break;
                }
            }
            if( i_channel_mask )
                msg_Warn( p_demux, "Some channels are unrecognized or uselessly specified (0x%x)", i_channel_mask );
            if( i_match < p_sys->fmt.audio.i_channels )
            {
                int i_missing = p_sys->fmt.audio.i_channels - i_match;
                msg_Warn( p_demux, "Trying to fill up unspecified position for %d channels", p_sys->fmt.audio.i_channels - i_match );

                static const uint32_t pi_pair[] = { AOUT_CHAN_REARLEFT|AOUT_CHAN_REARRIGHT,
                                                    AOUT_CHAN_MIDDLELEFT|AOUT_CHAN_MIDDLERIGHT,
                                                    AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT
                                                  };
                /* FIXME: Unused yet
                static const uint32_t pi_center[] = { AOUT_CHAN_REARCENTER,
                                                      0,
                                                      AOUT_CHAN_CENTER }; */

                /* Try to complete with pair */
                for( unsigned i = 0; i < sizeof(pi_pair)/sizeof(*pi_pair); i++ )
                {
                    if( i_missing >= 2 && !(p_sys->i_channel_mask & pi_pair[i] ) )
                    {
                        i_missing -= 2;
                        p_sys->i_channel_mask |= pi_pair[i];
                    }
                }
                /* Well fill up with what we can */
                for( unsigned i = 0; i < sizeof(pi_channels_in)/sizeof(*pi_channels_in) && i_missing > 0; i++ )
                {
                    if( !( p_sys->i_channel_mask & pi_channels_in[i] ) )
                    {
                        p_sys->i_channel_mask |= pi_channels_in[i];
                        i_missing--;

                        if( i_missing <= 0 )
                            break;
                    }
                }

                i_match = p_sys->fmt.audio.i_channels - i_missing;
            }
            if( i_match < p_sys->fmt.audio.i_channels )
            {
                msg_Err( p_demux, "Invalid/unsupported channel mask" );
                p_sys->i_channel_mask = 0;
            }
        }
    }
    else if( GetWLE( &p_wf->wFormatTag ) == WAVE_FORMAT_PCM &&
             p_sys->fmt.audio.i_channels > 2 && p_sys->fmt.audio.i_channels <= 9 )
    {
        for( int i = 0; i < p_sys->fmt.audio.i_channels; i++ )
            p_sys->i_channel_mask |= pi_channels_in[i];
    }

    if( p_sys->i_channel_mask )
    {
        if( p_sys->fmt.i_codec == VLC_FOURCC('a','r','a','w') ||
                p_sys->fmt.i_codec == VLC_FOURCC('p','c','m',' ') ||
                p_sys->fmt.i_codec == VLC_FOURCC('a','f','l','t') )
            p_sys->i_chans_to_reorder =
                aout_CheckChannelReorder( pi_channels_in, NULL,
                                          p_sys->i_channel_mask,
                                          p_sys->pi_chan_table );

        msg_Dbg( p_demux, "channel mask: %x, reordering: %u",
                 p_sys->i_channel_mask, p_sys->i_chans_to_reorder );
    }

    p_sys->fmt.audio.i_physical_channels =
        p_sys->fmt.audio.i_original_channels = p_sys->i_channel_mask;

    if( p_sys->fmt.i_extra > 0 )
    {
        p_sys->fmt.p_extra = malloc( p_sys->fmt.i_extra );
        if( unlikely(!p_sys->fmt.p_extra) )
        {
            p_sys->fmt.i_extra = 0;
            goto error;
        }
        memcpy( p_sys->fmt.p_extra, (uint8_t *)p_wf + sizeof( WAVEFORMATEX ) + i_extended,
                p_sys->fmt.i_extra );
    }

    msg_Dbg( p_demux, "format: 0x%4.4x, fourcc: %4.4s, channels: %d, "
             "freq: %u Hz, bitrate: %uKo/s, blockalign: %d, bits/samples: %d, "
             "extra size: %d",
             GetWLE( &p_wf->wFormatTag ), (char *)&p_sys->fmt.i_codec,
             p_sys->fmt.audio.i_channels, p_sys->fmt.audio.i_rate,
             p_sys->fmt.i_bitrate / 8 / 1024, p_sys->fmt.audio.i_blockalign,
             p_sys->fmt.audio.i_bitspersample, p_sys->fmt.i_extra );

    free( p_wf );
    p_wf = NULL;

    switch( p_sys->fmt.i_codec )
    {
    case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
    case VLC_FOURCC( 'a', 'f', 'l', 't' ):
    case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
    case VLC_CODEC_ALAW:
    case VLC_CODEC_MULAW:
    case VLC_FOURCC( 'p', 'c', 'm', ' ' ):
        if( FrameInfo_PCM( &p_sys->i_frame_size, &p_sys->i_frame_samples,
                           &p_sys->fmt ) )
            goto error;
        break;
    case VLC_CODEC_ADPCM_MS:
        if( FrameInfo_MS_ADPCM( &p_sys->i_frame_size, &p_sys->i_frame_samples,
                                &p_sys->fmt ) )
            goto error;
        break;
    case VLC_CODEC_ADPCM_IMA_WAV:
        if( FrameInfo_IMA_ADPCM( &p_sys->i_frame_size, &p_sys->i_frame_samples,
                                 &p_sys->fmt ) )
            goto error;
        break;
    case VLC_FOURCC( 'm', 's', 0x00, 0x61 ):
    case VLC_FOURCC( 'm', 's', 0x00, 0x62 ):
        /* FIXME not sure at all FIXME */
        if( FrameInfo_MS_ADPCM( &p_sys->i_frame_size, &p_sys->i_frame_samples,
                                &p_sys->fmt ) )
            goto error;
        break;
    case VLC_CODEC_MPGA:
    case VLC_CODEC_A52:
        /* FIXME set end of area FIXME */
        goto error;
    case VLC_CODEC_GSM_MS:
    case VLC_CODEC_ADPCM_G726:
    case VLC_CODEC_TRUESPEECH:
    case VLC_CODEC_ATRAC3:
    case VLC_CODEC_G723_1:
        if( FrameInfo_MSGSM( &p_sys->i_frame_size, &p_sys->i_frame_samples,
                             &p_sys->fmt ) )
            goto error;
        break;
    default:
        msg_Err( p_demux, "unsupported codec (%4.4s)",
                 (char*)&p_sys->fmt.i_codec );
        goto error;
    }

    if( p_sys->i_frame_size <= 0 || p_sys->i_frame_samples <= 0 )
    {
        msg_Dbg( p_demux, "invalid frame size: %i %i", p_sys->i_frame_size,
                 p_sys->i_frame_samples );
        goto error;
    }
    if( p_sys->fmt.audio.i_rate <= 0 )
    {
        msg_Dbg( p_demux, "invalid sample rate: %i", p_sys->fmt.audio.i_rate );
        goto error;
    }

    msg_Dbg( p_demux, "found %s audio format", psz_name );

    if( ChunkFind( p_demux, "data", &p_sys->i_data_size ) )
    {
        msg_Err( p_demux, "cannot find 'data' chunk" );
        goto error;
    }
    if( stream_Read( p_demux->s, NULL, 8 ) != 8 )
        goto error;
    p_sys->i_data_pos = stream_Tell( p_demux->s );

    if( p_sys->fmt.i_bitrate <= 0 )
    {
        p_sys->fmt.i_bitrate = (int64_t)p_sys->i_frame_size *
                               p_sys->fmt.audio.i_rate * 8 / p_sys->i_frame_samples;
    }

    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt );

    date_Init( &p_sys->pts, p_sys->fmt.audio.i_rate, 1 );
    date_Set( &p_sys->pts, 1 );

    return VLC_SUCCESS;

error:
    msg_Err( p_demux, "An error occurred during wav demuxing" );
    free( p_wf );
    free( p_sys );
    return VLC_EGENERIC;
}
예제 #12
0
파일: parse.c 프로젝트: AmirAbrams/haiku
/**
 * Parse header extension object. Takes a pointer to a newly allocated
 * header extension structure, a pointer to the data buffer and the 
 * length of the data buffer as its parameters. Subobject contents are
 * not parsed, but they are added as a linked list to the header object.
 */
static int
asf_parse_headerext(asf_object_headerext_t *header, uint8_t *buf, uint64_t buflen)
{
	int64_t datalen;
	uint8_t *data;

	if (header->size < 46) {
		/* invalide size for headerext */
		return ASF_ERROR_INVALID_OBJECT_SIZE;
	}

	/* Read reserved and datalen fields from the buffer */
	GetGUID(buf + 24, &header->reserved1);
	header->reserved2 = GetWLE(buf + 40);
	header->datalen = GetDWLE(buf + 42);

	if (header->datalen != header->size - 46) {
		/* invalid header extension data length value */
		return ASF_ERROR_INVALID_LENGTH;
	}
	header->data = buf + 46;

	debug_printf("parsing header extension subobjects");

	datalen = header->datalen;
	data = header->data;
	while (datalen > 0) {
		asfint_object_t *current;

		if (datalen < 24) {
			/* not enough data for reading a new object */
			break;
		}

		/* Allocate a new subobject */
		current = malloc(sizeof(asfint_object_t));
		if (!current) {
			return ASF_ERROR_OUTOFMEM;
		}

		asf_parse_read_object(current, data);
		if (current->size > datalen || current->size < 24) {
			/* invalid object size */
			break;
		}
		current->datalen = current->size - 24;
		current->data = data + 24;

		/* add to the list of subobjects */
		if (!header->first) {
			header->first = current;
			header->last = current;
		} else {
			header->last->next = current;
			header->last = current;
		}

		data += current->size;
		datalen -= current->size;
	}

	if (datalen != 0) {
		/* not enough data for reading the whole object */
		return ASF_ERROR_INVALID_LENGTH;
	}

	debug_printf("header extension subobjects parsed successfully");

	return header->size;
}
예제 #13
0
파일: xa.c 프로젝트: paa/vlc
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    xa_header_t p_xa;
    const uint8_t *p_buf;

    /* XA file heuristic */
    if( stream_Peek( p_demux->s, &p_buf, sizeof( p_xa ) )
            < (signed)sizeof( p_xa ) )
        return VLC_EGENERIC;

    memcpy( &p_xa, p_buf, sizeof( p_xa ) );
    if( ( strncmp( p_xa.xa_id, "XAI", 4 )
       && strncmp( p_xa.xa_id, "XAJ", 4 ) )
     || ( GetWLE( &p_xa.wFormatTag  ) != 0x0001)
     || ( GetWLE( &p_xa.wBitsPerSample ) != 16) )
        return VLC_EGENERIC;

    p_sys = malloc( sizeof( demux_sys_t ) );
    if( unlikely( p_sys == NULL ) )
        return VLC_ENOMEM;

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;
    p_sys->p_es         = NULL;

    /* skip XA header -- cannot fail */
    stream_Read( p_demux->s, NULL, sizeof( p_xa ) );

    es_format_Init( &p_sys->fmt, AUDIO_ES, VLC_FOURCC('X','A','J',0) );

    msg_Dbg( p_demux, "assuming EA ADPCM audio codec" );
    p_sys->fmt.audio.i_rate = GetDWLE( &p_xa.nSamplesPerSec );
    p_sys->fmt.audio.i_bytes_per_frame = 15 * GetWLE( &p_xa.nChannels );
    p_sys->fmt.audio.i_frame_length = 28; /* 28 samples of 4 bits each */

    p_sys->fmt.audio.i_channels = GetWLE ( &p_xa.nChannels );
    p_sys->fmt.audio.i_blockalign = p_sys->fmt.audio.i_bytes_per_frame;
    p_sys->fmt.audio.i_bitspersample = 16;
    p_sys->fmt.i_bitrate = (p_sys->fmt.audio.i_rate
                            * p_sys->fmt.audio.i_bytes_per_frame * 8)
                            / p_sys->fmt.audio.i_frame_length;
    p_sys->fmt.i_extra = 0;
    p_sys->fmt.p_extra = NULL;

    p_sys->i_data_offset = stream_Tell( p_demux->s );
    /* FIXME: better computation */
    p_sys->i_data_size = p_xa.iSize * 15 / 56;
    /* How many frames per block (1:1 is too CPU intensive) */
    p_sys->i_block_frames = p_sys->fmt.audio.i_rate / (28 * 20) + 1;

    msg_Dbg( p_demux, "fourcc: %4.4s, channels: %d, "
             "freq: %d Hz, bitrate: %dKo/s, blockalign: %d",
             (char *)&p_sys->fmt.i_codec, p_sys->fmt.audio.i_channels,
             p_sys->fmt.audio.i_rate, p_sys->fmt.i_bitrate / 8192,
             p_sys->fmt.audio.i_blockalign );

    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt );

    date_Init( &p_sys->pts, p_sys->fmt.audio.i_rate, 1 );
    date_Set( &p_sys->pts, 1 );

    return VLC_SUCCESS;
}
예제 #14
0
파일: parse.c 프로젝트: AmirAbrams/haiku
/**
 * Takes an initialized asf_file_t structure file as a parameter. Allocates
 * a new asf_object_header_t in file->header and uses the file->iostream to
 * read all fields and subobjects into it. Finally calls the
 * asf_parse_header_validate function to validate the values and parse the
 * commonly used values into the asf_file_t struct itself.
 */
int
asf_parse_header(asf_file_t *file)
{
	asf_object_header_t *header;
	asf_iostream_t *iostream;
	uint8_t hdata[30];
	int tmp;

	file->header = NULL;
	iostream = &file->iostream;

	/* object minimum is 24 bytes and header needs to have
	 * the subobject count field and two reserved fields */
	tmp = asf_byteio_read(iostream, hdata, 30);
	if (tmp < 0) {
		/* not enough data to read the header object */
		return tmp;
	}

	file->header = malloc(sizeof(asf_object_header_t));
	header = file->header;
	if (!header) {
		return ASF_ERROR_OUTOFMEM;
	}

	/* read the object and check its size value */
	asf_parse_read_object((asfint_object_t *) header, hdata);
	if (header->size < 30) {
		/* invalid size for header object */
		return ASF_ERROR_INVALID_OBJECT_SIZE;
	}

	/* read header object specific compulsory fields */
	header->subobjects = GetDWLE(hdata + 24);
	header->reserved1 = hdata[28];
	header->reserved2 = hdata[29];

	/* clear header extension object and subobject list */
	header->ext = NULL;
	header->first = NULL;
	header->last = NULL;

	/* the header data needs to be allocated for reading */
	header->datalen = header->size - 30;
	header->data = malloc(header->datalen * sizeof(uint8_t));
	if (!header->data) {
		return ASF_ERROR_OUTOFMEM;
	}

	tmp = asf_byteio_read(iostream, header->data, header->datalen);
	if (tmp < 0) {
		return tmp;
	}

	if (header->subobjects > 0) {
		uint64_t datalen;
		uint8_t *data;
		int i;

		debug_printf("starting to read subobjects");

		/* use temporary variables for use during the read */
		datalen = header->datalen;
		data = header->data;
		for (i=0; i<header->subobjects; i++) {
			asfint_object_t *current;

			if (datalen < 24) {
				/* not enough data for reading object */
				break;
			}

			current = malloc(sizeof(asfint_object_t));
			if (!current) {
				return ASF_ERROR_OUTOFMEM;
			}

			asf_parse_read_object(current, data);
			if (current->size > datalen || current->size < 24) {
				/* invalid object size */
				break;
			}

			/* Check if the current subobject is a header extension
			 * object or just a normal subobject */
			if (current->type == GUID_HEADER_EXTENSION && !header->ext) {
				int ret;
				asf_object_headerext_t *headerext;

				/* we handle header extension separately because it has
				 * some subobjects as well */
				current = realloc(current, sizeof(asf_object_headerext_t));
				headerext = (asf_object_headerext_t *) current;
				headerext->first = NULL;
				headerext->last = NULL;
				ret = asf_parse_headerext(headerext, data, datalen);

				if (ret < 0) {
					/* error parsing header extension */
					return ret;
				}

				header->ext = headerext;
			} else {
				if (current->type == GUID_HEADER_EXTENSION) {
					debug_printf("WARNING! Second header extension object found, ignoring it!");
				}

				current->datalen = current->size - 24;
				current->data = data + 24;

				/* add to list of subobjects */
				if (!header->first) {
					header->first = current;
					header->last = current;
				} else {
					header->last->next = current;
					header->last = current;
				}
			}

			data += current->size;
			datalen -= current->size;
		}

		if (i != header->subobjects || datalen != 0) {
			/* header data size doesn't match given subobject count */
			return ASF_ERROR_INVALID_VALUE;
		}

		debug_printf("%d subobjects read successfully", i);
	}

	tmp = asf_parse_header_validate(file, file->header);
	if (tmp < 0) {
		/* header read ok but doesn't validate correctly */
		return tmp;
	}

	debug_printf("header validated correctly");

	return header->size;
}
예제 #15
0
파일: parse.c 프로젝트: AmirAbrams/haiku
/**
 * Takes an initialized asf_file_t structure file as a parameter. Allocates
 * a new asf_object_index_t in file->index and uses the file->iostream to
 * read all its compulsory fields into it. Notice that the actual data is
 * not read in any way, because we need to be able to work with non-seekable
 * streams as well.
 */
int
asf_parse_index(asf_file_t *file)
{
	asf_object_index_t *index;
	asf_iostream_t *iostream;
	uint8_t idata[56];
	uint64_t entry_data_size;
	uint8_t *entry_data = NULL;
	int tmp, i;

	file->index = NULL;
	iostream = &file->iostream;

	/* read the raw data of an index header */
	tmp = asf_byteio_read(iostream, idata, 56);
	if (tmp < 0) {
		printf("Could not read index header\n");
		return tmp;
	}

	/* allocate the index object */
	index = malloc(sizeof(asf_object_index_t));
	if (!index) {
		return ASF_ERROR_OUTOFMEM;
	}

	asf_parse_read_object((asfint_object_t *) index, idata);
	if (index->type != GUID_INDEX) {
		tmp = index->size;
		free(index);

		/* The guid type was wrong, just return the bytes to skip */
		return tmp;
	}

	if (index->size < 56) {
		/* invalid size for index object */
		free(index);
		return ASF_ERROR_INVALID_OBJECT_SIZE;
	}

	GetGUID(idata + 24, &index->file_id);
	index->entry_time_interval = GetQWLE(idata + 40);
	index->max_packet_count = GetDWLE(idata + 48);
	index->entry_count = GetDWLE(idata + 52);

	printf("INDEX\n");
	printf("Total Index Entries %d\n",index->entry_count);
	printf("Index Size in bytes %Ld\n",index->size);
	printf("Index Max Packet Count %d\n",index->max_packet_count);
	printf("Index Entry Time Interval %Ld\n",index->entry_time_interval);
	
	if (index->entry_count == 0) {
		printf("Index has no entries\n");
		file->index = index;
		return index->size;
	}

	if (index->entry_count * 6 + 56 > index->size) {
		free(index);
		return ASF_ERROR_INVALID_LENGTH;
	}

	entry_data_size = index->entry_count * 6;
	entry_data = malloc(entry_data_size * sizeof(uint8_t));
	if (!entry_data) {
		free(index);
		return ASF_ERROR_OUTOFMEM;
	}
	tmp = asf_byteio_read(iostream, entry_data, entry_data_size);
	if (tmp < 0) {
		printf("Could not read entry data\n");
		free(index);
		free(entry_data);
		return tmp;
	}

	index->entries = malloc(index->entry_count * sizeof(asf_index_entry_t));
	if (!index->entries) {
		free(index);
		free(entry_data);
		return ASF_ERROR_OUTOFMEM;
	}

	for (i=0; i<index->entry_count; i++) {
		index->entries[i].packet_index = GetDWLE(entry_data + i*6);
		index->entries[i].packet_count = GetWLE(entry_data + i*6 + 4);
	}

	free(entry_data);
	file->index = index;

	return index->size;
}
예제 #16
0
파일: xa.c 프로젝트: mstorsjo/vlc
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    const uint8_t *peek;

    /* XA file heuristic */
    if( vlc_stream_Peek( p_demux->s, &peek, 10 ) < 10 )
        return VLC_EGENERIC;
    if( memcmp( peek, "XAI", 4 ) && memcmp( peek, "XAJ", 4 ) &&
            memcmp( peek, "XA\0", 4 ) )
        return VLC_EGENERIC;
    if( GetWLE( peek + 8 ) != 1 ) /* format tag */
        return VLC_EGENERIC;

    demux_sys_t *p_sys = vlc_obj_malloc( p_this, sizeof (*p_sys) );
    if( unlikely( p_sys == NULL ) )
        return VLC_ENOMEM;

    /* read XA header*/
    xa_header_t xa;

    if( vlc_stream_Read( p_demux->s, &xa, HEADER_LENGTH ) < HEADER_LENGTH )
        return VLC_EGENERIC;

    es_format_t fmt;
    es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_ADPCM_XA_EA );

    msg_Dbg( p_demux, "assuming EA ADPCM audio codec" );
    fmt.audio.i_rate = GetDWLE( &xa.nSamplesPerSec );
    fmt.audio.i_bytes_per_frame = 15 * GetWLE( &xa.nChannels );
    fmt.audio.i_frame_length = FRAME_LENGTH;

    fmt.audio.i_channels = GetWLE ( &xa.nChannels );
    fmt.audio.i_blockalign = fmt.audio.i_bytes_per_frame;
    fmt.audio.i_bitspersample = GetWLE( &xa.wBitsPerSample );
    fmt.i_bitrate = (fmt.audio.i_rate * fmt.audio.i_bytes_per_frame * 8)
                    / fmt.audio.i_frame_length;

    /* FIXME: better computation */
    p_sys->i_data_size = xa.iSize * 15 / 56;
    /* How many frames per block (1:1 is too CPU intensive) */
    p_sys->i_block_frames = fmt.audio.i_rate / (FRAME_LENGTH * 20) + 1;
    p_sys->i_frame_size = fmt.audio.i_bytes_per_frame;
    p_sys->i_bitrate = fmt.i_bitrate;

    msg_Dbg( p_demux, "fourcc: %4.4s, channels: %d, "
             "freq: %d Hz, bitrate: %dKo/s, blockalign: %d",
             (char *)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate,
             fmt.i_bitrate / 8192, fmt.audio.i_blockalign );

    if( fmt.audio.i_rate == 0 || fmt.audio.i_channels == 0
     || fmt.audio.i_bitspersample != 16 )
        return VLC_EGENERIC;

    p_sys->p_es = es_out_Add( p_demux->out, &fmt );
    if( unlikely(p_sys->p_es == NULL) )
        return VLC_ENOMEM;

    date_Init( &p_sys->pts, fmt.audio.i_rate, 1 );
    date_Set( &p_sys->pts, VLC_TICK_0 );

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;
    return VLC_SUCCESS;
}
예제 #17
0
파일: id3tag.c 프로젝트: FLYKingdom/vlc
static void ParseAPEvXTag( demux_meta_t *p_demux_meta, const uint8_t *p_data, int i_data )
{
    vlc_meta_t       *p_meta;
    bool b_start;
    bool b_end;
    const uint8_t *p_header = NULL;
    int i_entry;

    if( i_data < APE_TAG_HEADERSIZE )
        return;

    b_start = !strncmp( (char*)&p_data[0], "APETAGEX", 8 );
    b_end = !strncmp( (char*)&p_data[i_data-APE_TAG_HEADERSIZE], "APETAGEX", 8 );
    if( !b_end && !b_start )
        return;

    if( !p_demux_meta->p_meta )
        p_demux_meta->p_meta = vlc_meta_New();
    p_meta = p_demux_meta->p_meta;

    if( b_start )
    {
        p_header = &p_data[0];
        p_data += APE_TAG_HEADERSIZE;
        i_data -= APE_TAG_HEADERSIZE;
    }
    if( b_end )
    {
        p_header = &p_data[i_data-APE_TAG_HEADERSIZE];
        i_data -= APE_TAG_HEADERSIZE;
    }
    if( i_data <= 0 )
        return;

    i_entry = GetDWLE( &p_header[8+4+4] );
    if( i_entry <= 0 )
        return;

    while( i_entry > 0 && i_data >= 10 )
    {
        const int i_size = GetDWLE( &p_data[0] );
        const uint32_t flags = GetDWLE( &p_data[4] );
        char psz_name[256];
        int n;

        strlcpy( psz_name, (char*)&p_data[8], sizeof(psz_name) );
        n = strlen( psz_name );
        if( n <= 0 )
            break;

        p_data += 8+n+1;
        i_data -= 8+n+1;
        if( i_data < i_size )
            break;

        /* Retreive UTF-8 fields only */
        if( ((flags>>1) & 0x03) == 0x00 )
        {
            /* FIXME list are separated by '\0' */
            char *psz_value = strndup( (char*)&p_data[0], i_size );

            EnsureUTF8( psz_name );
            EnsureUTF8( psz_value );
#define IS(s) (!strcasecmp( psz_name, s ) )
            if( IS( "Title" ) )
                vlc_meta_SetTitle( p_meta, psz_value );
            else  if( IS( "Artist" ) )
                vlc_meta_SetArtist( p_meta, psz_value );
            else  if( IS( "Album" ) )
                vlc_meta_SetAlbum( p_meta, psz_value );
            else  if( IS( "Publisher" ) )
                vlc_meta_SetPublisher( p_meta, psz_value );
            else  if( IS( "Track" ) )
            {
                char *p = strchr( psz_value, '/' );
                if( p )
                    *p++ = '\0';
                vlc_meta_SetTrackNum( p_meta, psz_value );
            }
            else  if( IS( "Comment" ) )
                vlc_meta_SetDescription( p_meta, psz_value );
            else  if( IS( "Copyright" ) )
                vlc_meta_SetCopyright( p_meta, psz_value );
            else  if( IS( "Year" ) )
                vlc_meta_SetDate( p_meta, psz_value );
            else  if( IS( "Genre" ) )
                vlc_meta_SetGenre( p_meta, psz_value );
            else  if( IS( "Language" ) )
                vlc_meta_SetLanguage( p_meta, psz_value );
            else
                vlc_meta_AddExtra( p_meta, psz_name, psz_value );
#undef IS
            free( psz_value );
        }

        p_data += i_size;
        i_data -= i_size;
        i_entry--;
    }
}
예제 #18
0
/*****************************************************************************
 * Open: initializes ES structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    byte_t      *p_peek;
    int         i_peek = 0;
    vlc_bool_t  b_big_endian = 0; /* Arbitrary initialisation */

    /* Check if we are dealing with a WAV file */
    if( stream_Peek( p_demux->s, &p_peek, 12 ) == 12 &&
        !memcmp( p_peek, "RIFF", 4 ) && !memcmp( p_peek + 8, "WAVE", 4 ) )
    {
        int i_size;

        /* Skip the wave header */
        i_peek = 12 + 8;
        while( stream_Peek( p_demux->s, &p_peek, i_peek ) == i_peek &&
               memcmp( p_peek + i_peek - 8, "data", 4 ) )
        {
            i_peek += GetDWLE( p_peek + i_peek - 4 ) + 8;
        }

        /* TODO: should check wave format and sample_rate */

        /* Some A52 wav files don't begin with a sync code so we do a more
         * extensive search */
        i_size = stream_Peek( p_demux->s, &p_peek, i_peek + A52_PACKET_SIZE * 2);
        i_size -= (PCM_FRAME_SIZE + A52_MAX_HEADER_SIZE);

        while( i_peek < i_size )
        {
            if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
                /* The data is stored in 16 bits words */
                i_peek += 2;
            else
            {
                /* Check following sync code */
                if( CheckSync( p_peek + i_peek + PCM_FRAME_SIZE,
                               &b_big_endian ) != VLC_SUCCESS )
                {
                    i_peek += 2;
                    continue;
                }

                break;
            }
        }
    }

    /* Have a peep at the show. */
    if( stream_Peek( p_demux->s, &p_peek, i_peek + A52_MAX_HEADER_SIZE * 2 ) <
        i_peek + A52_MAX_HEADER_SIZE * 2 )
    {
        /* Stream too short */
        msg_Warn( p_demux, "cannot peek()" );
        return VLC_EGENERIC;
    }

    if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
    {
        if( strncmp( p_demux->psz_demux, "a52", 3 ) )
        {
            return VLC_EGENERIC;
        }

        /* User forced */
        msg_Err( p_demux, "this doesn't look like a A52 audio stream, "
                 "continuing anyway" );
    }

    /* Fill p_demux fields */
    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
    p_sys->b_start = VLC_TRUE;
    p_sys->i_mux_rate = 0;
    p_sys->b_big_endian = b_big_endian;

    /*
     * Load the A52 packetizer
     */
    p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_DECODER );
    p_sys->p_packetizer->pf_decode_audio = 0;
    p_sys->p_packetizer->pf_decode_video = 0;
    p_sys->p_packetizer->pf_decode_sub = 0;
    p_sys->p_packetizer->pf_packetize = 0;

    /* Initialization of decoder structure */
    es_format_Init( &p_sys->p_packetizer->fmt_in, AUDIO_ES,
                    VLC_FOURCC( 'a', '5', '2', ' ' ) );

    p_sys->p_packetizer->p_module =
        module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 );
    if( !p_sys->p_packetizer->p_module )
    {
        msg_Err( p_demux, "cannot find A52 packetizer" );
        return VLC_EGENERIC;
    }

    /* Create one program */
    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );

    return VLC_SUCCESS;
}
예제 #19
0
void vorbis_ParseComment( es_format_t *p_fmt, vlc_meta_t **pp_meta,
        const uint8_t *p_data, int i_data,
        int *i_attachments, input_attachment_t ***attachments,
        int *i_cover_score, int *i_cover_idx,
        int *i_seekpoint, seekpoint_t ***ppp_seekpoint,
        float (* ppf_replay_gain)[AUDIO_REPLAY_GAIN_MAX],
        float (* ppf_replay_peak)[AUDIO_REPLAY_GAIN_MAX] )
{
    int n;
    int i_comment;

    if( i_data < 8 )
        return;

    n = GetDWLE(p_data); RM(4);
    if( n < 0 || n > i_data )
        return;
#if 0
    if( n > 0 )
    {
        /* TODO report vendor string ? */
        char *psz_vendor = psz_vendor = strndup( p_data, n );
        free( psz_vendor );
    }
#endif
    RM(n);

    if( i_data < 4 )
        return;

    i_comment = GetDWLE(p_data); RM(4);
    if( i_comment <= 0 )
        return;

    /* */
    vlc_meta_t *p_meta = *pp_meta;
    if( !p_meta )
        *pp_meta = p_meta = vlc_meta_New();
    if( !p_meta )
        return;

    /* */
    bool hasTitle        = false;
    bool hasArtist       = false;
    bool hasGenre        = false;
    bool hasCopyright    = false;
    bool hasAlbum        = false;
    bool hasTrackNum     = false;
    bool hasDescription  = false;
    bool hasRating       = false;
    bool hasDate         = false;
    bool hasLanguage     = false;
    bool hasPublisher    = false;
    bool hasEncodedBy    = false;
    bool hasTrackTotal   = false;

    chapters_array_t chapters_array = { 0, NULL };

    for( ; i_comment > 0; i_comment-- )
    {
        char *psz_comment;
        if( i_data < 4 )
            break;
        n = GetDWLE(p_data); RM(4);
        if( n > i_data )
            break;
        if( n <= 0 )
            continue;

        psz_comment = strndup( (const char*)p_data, n );
        RM(n);

        EnsureUTF8( psz_comment );

#define IF_EXTRACT(txt,var) \
    if( !strncasecmp(psz_comment, txt, strlen(txt)) ) \
    { \
        const char *oldval = vlc_meta_Get( p_meta, vlc_meta_ ## var ); \
        if( oldval && has##var) \
        { \
            char * newval; \
            if( asprintf( &newval, "%s,%s", oldval, &psz_comment[strlen(txt)] ) == -1 ) \
                newval = NULL; \
            vlc_meta_Set( p_meta, vlc_meta_ ## var, newval ); \
            free( newval ); \
        } \
        else \
            vlc_meta_Set( p_meta, vlc_meta_ ## var, &psz_comment[strlen(txt)] ); \
        has##var = true; \
    }

#define IF_EXTRACT_ONCE(txt,var) \
    if( !strncasecmp(psz_comment, txt, strlen(txt)) && !has##var ) \
    { \
        vlc_meta_Set( p_meta, vlc_meta_ ## var, &psz_comment[strlen(txt)] ); \
        has##var = true; \
    }

#define IF_EXTRACT_FMT(txt,var,fmt,target) \
    IF_EXTRACT(txt,var)\
    if( fmt && !strncasecmp(psz_comment, txt, strlen(txt)) )\
        {\
            if ( fmt->target ) free( fmt->target );\
            fmt->target = strdup(&psz_comment[strlen(txt)]);\
        }

        IF_EXTRACT("TITLE=", Title )
        else IF_EXTRACT("ARTIST=", Artist )
        else IF_EXTRACT("GENRE=", Genre )
        else IF_EXTRACT("COPYRIGHT=", Copyright )
        else IF_EXTRACT("ALBUM=", Album )
        else if( !hasTrackNum && !strncasecmp(psz_comment, "TRACKNUMBER=", strlen("TRACKNUMBER=" ) ) )
        {
            /* Yeah yeah, such a clever idea, let's put xx/xx inside TRACKNUMBER
             * Oh, and let's not use TRACKTOTAL or TOTALTRACKS... */
            short unsigned u_track, u_total;
            if( sscanf( &psz_comment[strlen("TRACKNUMBER=")], "%hu/%hu", &u_track, &u_total ) == 2 )
            {
                char str[6];
                snprintf(str, 6, "%u", u_track);
                vlc_meta_Set( p_meta, vlc_meta_TrackNumber, str );
                hasTrackNum = true;
                snprintf(str, 6, "%u", u_total);
                vlc_meta_Set( p_meta, vlc_meta_TrackTotal, str );
                hasTrackTotal = true;
            }
            else
            {
                vlc_meta_Set( p_meta, vlc_meta_TrackNumber, &psz_comment[strlen("TRACKNUMBER=")] );
                hasTrackNum = true;
            }
        }
        else IF_EXTRACT_ONCE("TRACKTOTAL=", TrackTotal )
        else IF_EXTRACT_ONCE("TOTALTRACKS=", TrackTotal )
        else IF_EXTRACT("DESCRIPTION=", Description )
        else IF_EXTRACT("COMMENT=", Description )
        else IF_EXTRACT("COMMENTS=", Description )
        else IF_EXTRACT("RATING=", Rating )
        else IF_EXTRACT("DATE=", Date )
        else IF_EXTRACT_FMT("LANGUAGE=", Language, p_fmt, psz_language )
        else IF_EXTRACT("ORGANIZATION=", Publisher )
        else IF_EXTRACT("ENCODER=", EncodedBy )
        else if( !strncasecmp( psz_comment, "METADATA_BLOCK_PICTURE=", strlen("METADATA_BLOCK_PICTURE=")))
        {
            if( attachments == NULL )
                continue;

            uint8_t *p_picture;
            size_t i_size = vlc_b64_decode_binary( &p_picture, &psz_comment[strlen("METADATA_BLOCK_PICTURE=")]);
            input_attachment_t *p_attachment = ParseFlacPicture( p_picture,
                i_size, *i_attachments, i_cover_score, i_cover_idx );
            free( p_picture );
            if( p_attachment )
            {
                TAB_APPEND_CAST( (input_attachment_t**),
                    *i_attachments, *attachments, p_attachment );
            }
        }
        else if ( ppf_replay_gain && ppf_replay_peak && !strncmp(psz_comment, "REPLAYGAIN_", 11) )
        {
            char *p = strchr( psz_comment, '=' );
            if (!p) continue;
            if ( !strncasecmp(psz_comment, "REPLAYGAIN_TRACK_GAIN=", 22) )
            {
                (*ppf_replay_gain)[AUDIO_REPLAY_GAIN_TRACK] = us_atof( ++p );
            }
            else if ( !strncasecmp(psz_comment, "REPLAYGAIN_ALBUM_GAIN=", 22) )
            {
                (*ppf_replay_gain)[AUDIO_REPLAY_GAIN_ALBUM] = us_atof( ++p );
            }
            else if ( !strncasecmp(psz_comment, "REPLAYGAIN_ALBUM_PEAK=", 22) )
            {
                (*ppf_replay_peak)[AUDIO_REPLAY_GAIN_ALBUM] = us_atof( ++p );
            }
            else if ( !strncasecmp(psz_comment, "REPLAYGAIN_TRACK_PEAK=", 22) )
            {
                (*ppf_replay_peak)[AUDIO_REPLAY_GAIN_TRACK] = us_atof( ++p );
            }
        }
        else if( !strncasecmp(psz_comment, "CHAPTER", 7) )
        {
            unsigned int i_chapt;
            seekpoint_t *p_seekpoint = NULL;

            for( int i = 0; psz_comment[i] && psz_comment[i] != '='; i++ )
                if( psz_comment[i] >= 'a' && psz_comment[i] <= 'z' )
                    psz_comment[i] -= 'a' - 'A';

            if( strstr( psz_comment, "NAME=" ) &&
                    sscanf( psz_comment, "CHAPTER%uNAME=", &i_chapt ) == 1 )
            {
                char *p = strchr( psz_comment, '=' );
                p_seekpoint = getChapterEntry( i_chapt, &chapters_array );
                if ( !p || ! p_seekpoint ) continue;
                if ( ! p_seekpoint->psz_name )
                    p_seekpoint->psz_name = strdup( ++p );
            }
            else if( sscanf( psz_comment, "CHAPTER%u=", &i_chapt ) == 1 )
            {
                unsigned int h, m, s, ms;
                char *p = strchr( psz_comment, '=' );
                if( p && sscanf( ++p, "%u:%u:%u.%u", &h, &m, &s, &ms ) == 4 )
                {
                    p_seekpoint = getChapterEntry( i_chapt, &chapters_array );
                    if ( ! p_seekpoint ) continue;
                    p_seekpoint->i_time_offset =
                      (((int64_t)h * 3600 + (int64_t)m * 60 + (int64_t)s) * 1000 + ms) * 1000;
                }
            }
        }
        else if( strchr( psz_comment, '=' ) )
        {
            /* generic (PERFORMER/LICENSE/ORGANIZATION/LOCATION/CONTACT/ISRC,
             * undocumented tags and replay gain ) */
            char *p = strchr( psz_comment, '=' );
            *p++ = '\0';

            for( int i = 0; psz_comment[i]; i++ )
                if( psz_comment[i] >= 'a' && psz_comment[i] <= 'z' )
                    psz_comment[i] -= 'a' - 'A';

            vlc_meta_AddExtra( p_meta, psz_comment, p );
        }
#undef IF_EXTRACT
        free( psz_comment );
    }
예제 #20
0
    if( fseek( p_file, sizeof(index_record) * i_frame, SEEK_SET ) != 0 )
        return false;
    if( fread( &index_record, sizeof(index_record), 1, p_file ) < 1 )
        return false;

    /* VDR usually (only?) runs on little endian machines, but VLC has a
     * broader audience. See recording.* in VDR source for data layout. */
    if( b_ts )
    {
        uint64_t i_index_entry = GetQWLE( &index_record );
        *pi_offset = i_index_entry & UINT64_C(0xFFFFFFFFFF);
        *pi_file_num = i_index_entry >> 48;
    }
    else
    {
        *pi_offset = GetDWLE( &index_record );
        *pi_file_num = index_record[5];
    }

    return true;
}

/*****************************************************************************
 * Convert time stamp from file to frame number
 *****************************************************************************/
static int64_t ParseFrameNumber( const char *psz_line, float fps )
{
    unsigned h, m, s, f, n;

    /* hour:min:sec.frame (frame is optional) */
    n = sscanf( psz_line, "%u:%u:%u.%u", &h, &m, &s, &f );
예제 #21
0
파일: rar.c 프로젝트: Flameeyes/vlc
static int SkipFile(stream_t *s, int *count, rar_file_t ***file,
                    const rar_block_t *hdr, const char *volume_mrl)
{
    const uint8_t *peek;

    int min_size = 7+21;
    if (hdr->flags & RAR_BLOCK_FILE_HAS_HIGH)
        min_size += 8;
    if (hdr->size < (unsigned)min_size)
        return VLC_EGENERIC;

    if (stream_Peek(s, &peek, min_size) < min_size)
        return VLC_EGENERIC;

    /* */
    uint32_t file_size_low = GetDWLE(&peek[7+4]);
    uint8_t  method = peek[7+18];
    uint16_t name_size = GetWLE(&peek[7+19]);
    uint32_t file_size_high = 0;
    if (hdr->flags & RAR_BLOCK_FILE_HAS_HIGH)
        file_size_high = GetDWLE(&peek[7+25]);
    const uint64_t file_size = ((uint64_t)file_size_high << 32) | file_size_low;

    char *name = calloc(1, name_size + 1);
    if (!name)
        return VLC_EGENERIC;

    const int name_offset = (hdr->flags & RAR_BLOCK_FILE_HAS_HIGH) ? (7+33) : (7+25);
    if (name_offset + name_size <= hdr->size) {
        const int max_size = name_offset + name_size;
        if (stream_Peek(s, &peek, max_size) < max_size) {
            free(name);
            return VLC_EGENERIC;
        }
        memcpy(name, &peek[name_offset], name_size);
    }

    rar_file_t *current = NULL;
    if (method != 0x30) {
        msg_Warn(s, "Ignoring compressed file %s (method=0x%2.2x)", name, method);
        goto exit;
    }

    /* */
    if( *count > 0 )
        current = (*file)[*count - 1];

    if (current &&
        (current->is_complete ||
          strcmp(current->name, name) ||
          (hdr->flags & RAR_BLOCK_FILE_HAS_PREVIOUS) == 0))
        current = NULL;

    if (!current) {
        if (hdr->flags & RAR_BLOCK_FILE_HAS_PREVIOUS)
            goto exit;
        current = malloc(sizeof(*current));
        if (!current)
            goto exit;
        TAB_APPEND(*count, *file, current);

        current->name = name;
        current->size = file_size;
        current->is_complete = false;
        current->real_size = 0;
        TAB_INIT(current->chunk_count, current->chunk);

        name = NULL;
    }

    /* Append chunks */
    rar_file_chunk_t *chunk = malloc(sizeof(*chunk));
    if (chunk) {
        chunk->mrl = strdup(volume_mrl);
        chunk->offset = stream_Tell(s) + hdr->size;
        chunk->size = hdr->add_size;
        chunk->cummulated_size = 0;
        if (current->chunk_count > 0) {
            rar_file_chunk_t *previous = current->chunk[current->chunk_count-1];

            chunk->cummulated_size += previous->cummulated_size +
                                      previous->size;
        }

        TAB_APPEND(current->chunk_count, current->chunk, chunk);

        current->real_size += hdr->add_size;
    }
    if ((hdr->flags & RAR_BLOCK_FILE_HAS_NEXT) == 0)
        current->is_complete = true;

exit:
    /* */
    free(name);

    /* We stop on the first non empty file if we cannot seek */
    if (current) {
        bool can_seek = false;
        stream_Control(s, STREAM_CAN_SEEK, &can_seek);
        if (!can_seek && current->size > 0)
            return VLC_EGENERIC;
    }

    if (SkipBlock(s, hdr))
        return VLC_EGENERIC;
    return VLC_SUCCESS;
}
예제 #22
0
파일: smf.c 프로젝트: CSRedRat/vlc
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open (vlc_object_t * p_this)
{
    demux_t       *p_demux = (demux_t *)p_this;
    stream_t      *stream = p_demux->s;
    demux_sys_t   *p_sys;
    const uint8_t *peek;
    unsigned       tracks, ppqn;
    bool     multitrack;

    /* (Try to) parse the SMF header */
    /* Header chunk always has 6 bytes payload */
    if (stream_Peek (stream, &peek, 14) < 14)
        return VLC_EGENERIC;

    /* Skip RIFF MIDI header if present */
    if (!memcmp (peek, "RIFF", 4) && !memcmp (peek + 8, "RMID", 4))
    {
        uint32_t riff_len = GetDWLE (peek + 4);

        msg_Dbg (p_this, "detected RIFF MIDI file (%u bytes)",
                 (unsigned)riff_len);
        if ((stream_Read (stream, NULL, 12) < 12))
            return VLC_EGENERIC;

        /* Look for the RIFF data chunk */
        for (;;)
        {
            char chnk_hdr[8];
            uint32_t chnk_len;

            if ((riff_len < 8)
             || (stream_Read (stream, chnk_hdr, 8) < 8))
                return VLC_EGENERIC;

            riff_len -= 8;
            chnk_len = GetDWLE (chnk_hdr + 4);
            if (riff_len < chnk_len)
                return VLC_EGENERIC;
            riff_len -= chnk_len;

            if (!memcmp (chnk_hdr, "data", 4))
                break; /* found! */

            if (stream_Read (stream, NULL, chnk_len) < (ssize_t)chnk_len)
                return VLC_EGENERIC;
        }

        /* Read real SMF header. Assume RIFF data chunk length is proper. */
        if (stream_Peek (stream, &peek, 14) < 14)
            return VLC_EGENERIC;
    }

    if (memcmp (peek, "MThd\x00\x00\x00\x06", 8))
        return VLC_EGENERIC;
    peek += 8;

    /* First word: SMF type */
    switch (GetWBE (peek))
    {
        case 0:
            multitrack = false;
            break;
        case 1:
            multitrack = true;
            break;
        default:
            /* We don't implement SMF2 (as do many) */
            msg_Err (p_this, "unsupported SMF file type %u", GetWBE (peek));
            return VLC_EGENERIC;
    }
    peek += 2;

    /* Second word: number of tracks */
    tracks = GetWBE (peek);
    peek += 2;
    if (!multitrack && (tracks != 1))
    {
        msg_Err (p_this, "invalid SMF type 0 file");
        return VLC_EGENERIC;
    }

    msg_Dbg (p_this, "detected Standard MIDI File (type %u) with %u track(s)",
             multitrack, tracks);

    /* Third/last word: timing */
    ppqn = GetWBE (peek);
    if (ppqn & 0x8000)
    {
        /* FIXME */
        msg_Err (p_this, "SMPTE timestamps not implemented");
        return VLC_EGENERIC;
    }
    else
    {
        msg_Dbg (p_this, " %u pulses per quarter note", ppqn);
    }

    p_sys = malloc (sizeof (*p_sys) + (sizeof (mtrk_t) * tracks));
    if (p_sys == NULL)
        return VLC_ENOMEM;

    /* We've had a valid SMF header - now skip it*/
    if (stream_Read (stream, NULL, 14) < 14)
        goto error;

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;

    /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */
    date_Init (&p_sys->pts, ppqn * 2, 1);
    date_Set (&p_sys->pts, 0);
    p_sys->pulse        = 0;
    p_sys->ppqn         = ppqn;

    p_sys->trackc       = tracks;
    /* Prefetch track offsets */
    for (unsigned i = 0; i < tracks; i++)
    {
        uint8_t head[8];

        if (i > 0)
        {
            /* Seeking screws streaming up, but there is no way around this,
             * as SMF1 tracks are performed simultaneously.
             * Not a big deal as SMF1 are usually only a few kbytes anyway. */
            if (stream_Seek (stream,  p_sys->trackv[i-1].end))
            {
                msg_Err (p_this, "cannot build SMF index (corrupted file?)");
                goto error;
            }
        }

        for (;;)
        {
            if (stream_Read (stream, head, 8) < 8)
            {
                /* FIXME: don't give up if we have at least one valid track */
                msg_Err (p_this, "incomplete SMF chunk, file is corrupted");
                goto error;
            }

            if (memcmp (head, "MTrk", 4) == 0)
                break;

            msg_Dbg (p_this, "skipping unknown SMF chunk");
            stream_Read (stream, NULL, GetDWBE (head + 4));
        }

        p_sys->trackv[i].offset = stream_Tell (stream);
        p_sys->trackv[i].end = p_sys->trackv[i].offset + GetDWBE (head + 4);
        p_sys->trackv[i].next = 0;
        ReadDeltaTime (stream, p_sys->trackv + i);
        p_sys->trackv[i].running_event = 0xF6;
        /* Why 0xF6 (Tuning Calibration)?
         * Because it has zero bytes of data, so the parser will detect the
         * error if the first event uses running status. */
    }

    es_format_t  fmt;
    es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MIDI);
    fmt.audio.i_channels = 2;
    fmt.audio.i_rate = 44100; /* dummy value */
    p_sys->es = es_out_Add (p_demux->out, &fmt);

    return VLC_SUCCESS;

error:
    free (p_sys);
    return VLC_EGENERIC;
}