[vlc-devel] [PATCH v4 2/2] demux: wav: support parsing INFO chunk

Rémi Denis-Courmont remi at remlab.net
Sat Sep 26 11:22:24 CEST 2020


Le lauantaina 26. syyskuuta 2020, 11.20.51 EEST Zhao, Gang a écrit :
> Signed-off-by: Zhao, Gang <gang.zhao.42 at gmail.com>
> ---
>  modules/demux/wav.c | 188 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 188 insertions(+)
> 
> diff --git modules/demux/wav.c modules/demux/wav.c
> index 52f9639ef9..8cb1e86836 100644
> --- modules/demux/wav.c
> +++ modules/demux/wav.c
> @@ -36,6 +36,8 @@
>  #include <vlc_demux.h>
>  #include <vlc_aout.h>
>  #include <vlc_codecs.h>
> +#include <vlc_charset.h>
> +#include <vlc_meta.h>
> 
>  #include "windows_audio_commons.h"
> 
> @@ -58,12 +60,39 @@ typedef struct
>      uint32_t i_channel_mask;
>      uint8_t i_chans_to_reorder;            /* do we need channel reordering
> */ uint8_t pi_chan_table[AOUT_CHAN_MAX];
> +
> +    vlc_meta_t    *p_meta;

Is part of the patch missing?
It looks like p_meta is write-only?

>  } demux_sys_t;
> 
>  enum wav_chunk_id {
> +    wav_chunk_id_list,
>      wav_chunk_id_data,
>      wav_chunk_id_ds64,
>      wav_chunk_id_fmt,
> +
> +    wav_info_chunk_id_iarl,
> +    wav_info_chunk_id_iart,
> +    wav_info_chunk_id_icms,
> +    wav_info_chunk_id_icmt,
> +    wav_info_chunk_id_icop,
> +    wav_info_chunk_id_icrd,
> +    wav_info_chunk_id_icrp,
> +    wav_info_chunk_id_idim,
> +    wav_info_chunk_id_idpi,
> +    wav_info_chunk_id_ieng,
> +    wav_info_chunk_id_ignr,
> +    wav_info_chunk_id_ikey,
> +    wav_info_chunk_id_ilgt,
> +    wav_info_chunk_id_imed,
> +    wav_info_chunk_id_inam,
> +    wav_info_chunk_id_iplt,
> +    wav_info_chunk_id_iprd,
> +    wav_info_chunk_id_isbj,
> +    wav_info_chunk_id_isft,
> +    wav_info_chunk_id_ishp,
> +    wav_info_chunk_id_isrc,
> +    wav_info_chunk_id_isrf,
> +    wav_info_chunk_id_itch,
>  };
> 
>  struct wav_chunk_id_key
> @@ -74,12 +103,50 @@ struct wav_chunk_id_key
> 
>  static const struct wav_chunk_id_key wav_chunk_id_key_list[] =  {
>      /* Alphabetical order */
> +    { wav_chunk_id_list, "LIST" },
>      { wav_chunk_id_data, "data" },
>      { wav_chunk_id_ds64, "ds64" },
>      { wav_chunk_id_fmt,  "fmt " },
>  };
>  static const size_t wav_chunk_id_key_count =
> ARRAY_SIZE(wav_chunk_id_key_list);
> 
> +static const struct wav_chunk_id_key wav_info_chunk_id_key_list[] =  {
> +    /* Alphabetical order */
> +    { wav_info_chunk_id_iarl, "IARL" },
> +    { wav_info_chunk_id_iart, "IART" },
> +    { wav_info_chunk_id_icms, "ICMS" },
> +    { wav_info_chunk_id_icmt, "ICMT" },
> +    { wav_info_chunk_id_icop, "ICOP" },
> +    { wav_info_chunk_id_icrd, "ICRD" },
> +    { wav_info_chunk_id_icrp, "ICRP" },
> +    { wav_info_chunk_id_idim, "IDIM" },
> +    { wav_info_chunk_id_idpi, "IDPI" },
> +    { wav_info_chunk_id_ieng, "IENG" },
> +    { wav_info_chunk_id_ignr, "IGNR" },
> +    { wav_info_chunk_id_ikey, "IKEY" },
> +    { wav_info_chunk_id_ilgt, "ILGT" },
> +    { wav_info_chunk_id_imed, "IMED" },
> +    { wav_info_chunk_id_inam, "INAM" },
> +    { wav_info_chunk_id_iplt, "IPLT" },
> +    { wav_info_chunk_id_iprd, "IPRD" },
> +    { wav_info_chunk_id_isbj, "ISBJ" },
> +    { wav_info_chunk_id_isft, "ISFT" },
> +    { wav_info_chunk_id_ishp, "ISHP" },
> +    { wav_info_chunk_id_isrc, "ISRC" },
> +    { wav_info_chunk_id_isrf, "ISRF" },
> +    { wav_info_chunk_id_itch, "ITCH" },
> +};
> +static const size_t wav_info_chunk_id_key_count =
> ARRAY_SIZE(wav_info_chunk_id_key_list);
> +
> +/* get string type of INFO chunk id from enum */
> +static const char *wav_info_chunk_id_to_key(enum wav_chunk_id id)
> +{
> +    if ( id < wav_info_chunk_id_iarl || id > wav_info_chunk_id_itch )
> +        return "";

Should maybe assert() instead?

> +
> +    return wav_info_chunk_id_key_list[id - wav_info_chunk_id_iarl].key;
> +}
> +
>  static int
>  wav_chunk_CompareCb(const void *a, const void *b)
>  {
> @@ -320,6 +387,10 @@ static void Close ( vlc_object_t * p_this )
>      demux_sys_t *p_sys   = p_demux->p_sys;
> 
>      es_format_Clean( &p_sys->fmt );
> +
> +    if( p_sys->p_meta )
> +        vlc_meta_Delete( p_sys->p_meta );
> +
>      free( p_sys );
>  }
> 
> @@ -594,6 +665,115 @@ error:
>      return VLC_EGENERIC;
>  }
> 
> +static int ChunkParseINFO( demux_t *p_demux, uint32_t i_size )
> +{
> +    demux_sys_t *p_sys = p_demux->p_sys;
> +    const uint8_t *p_peek;
> +    enum wav_chunk_id id;
> +    uint32_t chunk_size;
> +    int meta_type;
> +    char *meta_value;
> +
> +    p_sys->p_meta = vlc_meta_New();
> +    if( p_sys->p_meta == NULL )
> +    {
> +        msg_Err( p_demux, "vlc_meta_New failed" );

We don't typically print errors on memory failure since that also requires 
allocating memory.

> +        return VLC_EGENERIC;
> +    }
> +
> +    while (i_size > 0) {
> +        int ret = ChunkGetNext( p_demux, &id, &chunk_size,
> +                                wav_info_chunk_id_key_list,
> +                                wav_info_chunk_id_key_count );
> +        if ( ret != VLC_SUCCESS )
> +            break;
> +
> +        /* chunk id(4 bytes) and chunk size(4 bytes) consumed by
> ChunkGetNext */
> +        i_size -= 8;
> +
> +        if( chunk_size == 0 )
> +        {
> +            msg_Err( p_demux, "invalid chunk with a size 0" );
> +            return VLC_EGENERIC;
> +        }
> +
> +        if( vlc_stream_Peek( p_demux->s, &p_peek, chunk_size ) !=
> chunk_size )

Please don't peek potentially large arrays.
Allocate a buffer and read into it.

> +            return VLC_EGENERIC;
> +
> +        meta_value = strndup( (const char *)p_peek, chunk_size );
> +        if (meta_value == NULL)
> +            return VLC_EGENERIC;
> +
> +        EnsureUTF8( meta_value );
> +
> +        meta_type = -1;
> +        switch( id )
> +        {
> +        case wav_info_chunk_id_iart:
> +            meta_type = vlc_meta_Artist;
> +            break;
> +        case wav_info_chunk_id_icop:
> +            meta_type = vlc_meta_Copyright;
> +            break;
> +        case wav_info_chunk_id_icrd:
> +            meta_type = vlc_meta_Date;
> +            break;
> +        case wav_info_chunk_id_ignr:
> +            meta_type = vlc_meta_Genre;
> +            break;
> +        case wav_info_chunk_id_inam:
> +            meta_type = vlc_meta_Title;
> +            break;
> +        default:
> +            /* no relevant meta type in vlc */
> +            break;
> +        }
> +
> +        msg_Dbg( p_demux, "id: %s meta_type: %d meta_value: %s\n",
> +                 wav_info_chunk_id_to_key(id), meta_type, meta_value );
> +
> +        if (meta_type != -1)
> +            vlc_meta_Set( p_sys->p_meta, meta_type, meta_value );
> +        else
> +            vlc_meta_AddExtra( p_sys->p_meta,
> +                               wav_info_chunk_id_key_list[id].key,
> meta_value );
> +
> +        free( meta_value );
> +        if( ChunkSkip( p_demux, chunk_size ) != VLC_SUCCESS )
> +            return VLC_EGENERIC;
> +
> +        i_size -= chunk_size;
> +    }
> +
> +    return VLC_SUCCESS;
> +}
> +
> +static int ChunkParseLIST( demux_t *p_demux, uint32_t i_size )
> +{
> +    const uint8_t *p_peek;
> +
> +    /* must have four bytes list type */
> +    if( i_size < 4 )
> +    {
> +        msg_Err( p_demux, "invalid 'LIST' chunk" );
> +        return VLC_EGENERIC;
> +    }
> +
> +    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) != 4 )
> +        return VLC_EGENERIC;
> +
> +    /* only care about INFO chunk */
> +    if ( memcmp(p_peek, "INFO", 4) != 0 ) {
> +        return ChunkSkip( p_demux, i_size );
> +    }
> +
> +    if ( vlc_stream_Read( p_demux->s, NULL, 4) != 4 )
> +        return VLC_EGENERIC;
> +
> +    i_size -= 4;
> +    return ChunkParseINFO( p_demux, i_size );
> +}
> +
>  static int Open( vlc_object_t * p_this )
>  {
>      demux_t     *p_demux = (demux_t*)p_this;
> @@ -684,6 +864,14 @@ static int Open( vlc_object_t * p_this )
>                  if( ChunkParseFmt( p_demux, i_size ) != VLC_SUCCESS )
>                      goto error;
>                  break;
> +            case wav_chunk_id_list:
> +                if( ChunkParseLIST( p_demux, i_size ) != VLC_SUCCESS )
> +                    goto error;
> +                break;
> +            default:
> +                if( ChunkSkip( p_demux, i_size ) != VLC_SUCCESS )
> +                    goto error;
> +                break;
>          }
>      }


-- 
Реми Дёни-Курмон
http://www.remlab.net/





More information about the vlc-devel mailing list