[vlc-devel] [PATCH] demux: wav: support parsing INFO chunk
Sean McGovern
gseanmcg at gmail.com
Sat Sep 12 17:56:55 CEST 2020
Nit: you spelled "parsing" correctly in the title but not in the commit
text.
Sean McGovern
On Sat., Sep. 12, 2020, 10:09 Zhao, Gang, <gang.zhao.42 at gmail.com> wrote:
> Paring INFO chunk and save meta data to vlc.
>
> Feature ticket: https://trac.videolan.org/vlc/ticket/6587
>
> Signed-off-by: Zhao, Gang <gang.zhao.42 at gmail.com>
> ---
> Tested that the code successfully got and saved meta data in the four test
> wav files.
>
> modules/demux/wav.c | 216 ++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 207 insertions(+), 9 deletions(-)
>
> diff --git modules/demux/wav.c modules/demux/wav.c
> index 4b0623412f..75b37d5be0 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,26 +60,96 @@ 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;
> } 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,
> };
>
> -static const struct wav_chunk_id_key
> +struct wav_chunk_id_key
> {
> enum wav_chunk_id id;
> char key[5];
> -} wav_chunk_id_key_list[] = {
> +};
> +
> +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);
> +
> +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 "";
> +
> + for ( int i = 0; i < wav_info_chunk_id_key_count; i++)
> + if (wav_info_chunk_id_key_list[i].id == id)
> + return wav_info_chunk_id_key_list[i].key;
> +
> + return "";
> +}
> +
> static int
> wav_chunk_CompareCb(const void *a, const void *b)
> {
> @@ -190,13 +262,14 @@ static int ChunkSkip( demux_t *p_demux, uint32_t
> i_size )
> }
>
> static int ChunkGetNext( demux_t *p_demux, enum wav_chunk_id *p_id,
> - uint32_t *pi_size )
> + uint32_t *pi_size,
> + const struct wav_chunk_id_key *id_key_list,
> size_t count )
> {
> #ifndef NDEBUG
> /* assert that keys are in alphabetical order */
> - for( size_t i = 0; i < wav_chunk_id_key_count - 1; ++i )
> - assert( strcmp( wav_chunk_id_key_list[i].key,
> - wav_chunk_id_key_list[i + 1].key ) < 0 );
> + for( size_t i = 0; i < count - 1; ++i )
> + assert( strcmp( id_key_list[i].key,
> + id_key_list[i + 1].key ) < 0 );
> #endif
>
> for( ;; )
> @@ -206,8 +279,8 @@ static int ChunkGetNext( demux_t *p_demux, enum
> wav_chunk_id *p_id,
> return VLC_EGENERIC;
>
> const struct wav_chunk_id_key *id =
> - bsearch( p_peek, wav_chunk_id_key_list,
> wav_chunk_id_key_count,
> - sizeof(*wav_chunk_id_key_list), wav_chunk_CompareCb
> );
> + bsearch( p_peek, id_key_list, count,
> + sizeof(*id_key_list), wav_chunk_CompareCb );
> uint32_t i_size = GetDWLE( p_peek + 4 );
>
> if( id == NULL )
> @@ -317,6 +390,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 );
> }
>
> @@ -591,6 +668,114 @@ 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;
> +
> + if( (p_sys->p_meta = vlc_meta_New()) == NULL )
> + {
> + msg_Err( p_demux, "vlc_meta_New failed" );
> + 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 )
> + 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;
> @@ -629,8 +814,13 @@ static int Open( vlc_object_t * p_this )
>
> bool eof = false;
> enum wav_chunk_id id;
> - while( !eof && ( ChunkGetNext( p_demux, &id, &i_size ) ) ==
> VLC_SUCCESS )
> + while( !eof )
> {
> + int ret = ChunkGetNext( p_demux, &id, &i_size,
> + wav_chunk_id_key_list,
> wav_chunk_id_key_count );
> + if (ret != VLC_SUCCESS )
> + break;
> +
> if( i_size == 0 )
> {
> msg_Err( p_demux, "invalid chunk with a size 0");
> @@ -676,6 +866,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;
> }
> }
>
> --
> 2.25.1
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20200912/fc82f9b2/attachment.html>
More information about the vlc-devel
mailing list