<div dir="auto">Nit: you spelled "parsing" correctly in the title but not in the commit text.<br><br><div data-smartmail="gmail_signature">Sean McGovern</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat., Sep. 12, 2020, 10:09 Zhao, Gang, <<a href="mailto:gang.zhao.42@gmail.com">gang.zhao.42@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Paring INFO chunk and save meta data to vlc.<br>
<br>
Feature ticket: <a href="https://trac.videolan.org/vlc/ticket/6587" rel="noreferrer noreferrer" target="_blank">https://trac.videolan.org/vlc/ticket/6587</a><br>
<br>
Signed-off-by: Zhao, Gang <<a href="mailto:gang.zhao.42@gmail.com" target="_blank" rel="noreferrer">gang.zhao.42@gmail.com</a>><br>
---<br>
Tested that the code successfully got and saved meta data in the four test wav files.<br>
<br>
modules/demux/wav.c | 216 ++++++++++++++++++++++++++++++++++++++++++--<br>
1 file changed, 207 insertions(+), 9 deletions(-)<br>
<br>
diff --git modules/demux/wav.c modules/demux/wav.c<br>
index 4b0623412f..75b37d5be0 100644<br>
--- modules/demux/wav.c<br>
+++ modules/demux/wav.c<br>
@@ -36,6 +36,8 @@<br>
#include <vlc_demux.h><br>
#include <vlc_aout.h><br>
#include <vlc_codecs.h><br>
+#include <vlc_charset.h><br>
+#include <vlc_meta.h><br>
<br>
#include "windows_audio_commons.h"<br>
<br>
@@ -58,26 +60,96 @@ typedef struct<br>
uint32_t i_channel_mask;<br>
uint8_t i_chans_to_reorder; /* do we need channel reordering */<br>
uint8_t pi_chan_table[AOUT_CHAN_MAX];<br>
+<br>
+ vlc_meta_t *p_meta;<br>
} demux_sys_t;<br>
<br>
enum wav_chunk_id {<br>
+ wav_chunk_id_list,<br>
wav_chunk_id_data,<br>
wav_chunk_id_ds64,<br>
wav_chunk_id_fmt,<br>
+<br>
+ wav_info_chunk_id_iarl,<br>
+ wav_info_chunk_id_iart,<br>
+ wav_info_chunk_id_icms,<br>
+ wav_info_chunk_id_icmt,<br>
+ wav_info_chunk_id_icop,<br>
+ wav_info_chunk_id_icrd,<br>
+ wav_info_chunk_id_icrp,<br>
+ wav_info_chunk_id_idim,<br>
+ wav_info_chunk_id_idpi,<br>
+ wav_info_chunk_id_ieng,<br>
+ wav_info_chunk_id_ignr,<br>
+ wav_info_chunk_id_ikey,<br>
+ wav_info_chunk_id_ilgt,<br>
+ wav_info_chunk_id_imed,<br>
+ wav_info_chunk_id_inam,<br>
+ wav_info_chunk_id_iplt,<br>
+ wav_info_chunk_id_iprd,<br>
+ wav_info_chunk_id_isbj,<br>
+ wav_info_chunk_id_isft,<br>
+ wav_info_chunk_id_ishp,<br>
+ wav_info_chunk_id_isrc,<br>
+ wav_info_chunk_id_isrf,<br>
+ wav_info_chunk_id_itch,<br>
};<br>
<br>
-static const struct wav_chunk_id_key<br>
+struct wav_chunk_id_key<br>
{<br>
enum wav_chunk_id id;<br>
char key[5];<br>
-} wav_chunk_id_key_list[] = {<br>
+};<br>
+<br>
+static const struct wav_chunk_id_key wav_chunk_id_key_list[] = {<br>
/* Alphabetical order */<br>
+ { wav_chunk_id_list, "LIST" },<br>
{ wav_chunk_id_data, "data" },<br>
{ wav_chunk_id_ds64, "ds64" },<br>
{ wav_chunk_id_fmt, "fmt " },<br>
};<br>
static const size_t wav_chunk_id_key_count = ARRAY_SIZE(wav_chunk_id_key_list);<br>
<br>
+static const struct wav_chunk_id_key wav_info_chunk_id_key_list[] = {<br>
+ /* Alphabetical order */<br>
+ { wav_info_chunk_id_iarl, "IARL" },<br>
+ { wav_info_chunk_id_iart, "IART" },<br>
+ { wav_info_chunk_id_icms, "ICMS" },<br>
+ { wav_info_chunk_id_icmt, "ICMT" },<br>
+ { wav_info_chunk_id_icop, "ICOP" },<br>
+ { wav_info_chunk_id_icrd, "ICRD" },<br>
+ { wav_info_chunk_id_icrp, "ICRP" },<br>
+ { wav_info_chunk_id_idim, "IDIM" },<br>
+ { wav_info_chunk_id_idpi, "IDPI" },<br>
+ { wav_info_chunk_id_ieng, "IENG" },<br>
+ { wav_info_chunk_id_ignr, "IGNR" },<br>
+ { wav_info_chunk_id_ikey, "IKEY" },<br>
+ { wav_info_chunk_id_ilgt, "ILGT" },<br>
+ { wav_info_chunk_id_imed, "IMED" },<br>
+ { wav_info_chunk_id_inam, "INAM" },<br>
+ { wav_info_chunk_id_iplt, "IPLT" },<br>
+ { wav_info_chunk_id_iprd, "IPRD" },<br>
+ { wav_info_chunk_id_isbj, "ISBJ" },<br>
+ { wav_info_chunk_id_isft, "ISFT" },<br>
+ { wav_info_chunk_id_ishp, "ISHP" },<br>
+ { wav_info_chunk_id_isrc, "ISRC" },<br>
+ { wav_info_chunk_id_isrf, "ISRF" },<br>
+ { wav_info_chunk_id_itch, "ITCH" },<br>
+};<br>
+static const size_t wav_info_chunk_id_key_count = ARRAY_SIZE(wav_info_chunk_id_key_list);<br>
+<br>
+static const char *wav_info_chunk_id_to_key(enum wav_chunk_id id)<br>
+{<br>
+ if ( id < wav_info_chunk_id_iarl || id > wav_info_chunk_id_itch )<br>
+ return "";<br>
+<br>
+ for ( int i = 0; i < wav_info_chunk_id_key_count; i++)<br>
+ if (wav_info_chunk_id_key_list[i].id == id)<br>
+ return wav_info_chunk_id_key_list[i].key;<br>
+<br>
+ return "";<br>
+}<br>
+<br>
static int<br>
wav_chunk_CompareCb(const void *a, const void *b)<br>
{<br>
@@ -190,13 +262,14 @@ static int ChunkSkip( demux_t *p_demux, uint32_t i_size )<br>
}<br>
<br>
static int ChunkGetNext( demux_t *p_demux, enum wav_chunk_id *p_id,<br>
- uint32_t *pi_size )<br>
+ uint32_t *pi_size,<br>
+ const struct wav_chunk_id_key *id_key_list, size_t count )<br>
{<br>
#ifndef NDEBUG<br>
/* assert that keys are in alphabetical order */<br>
- for( size_t i = 0; i < wav_chunk_id_key_count - 1; ++i )<br>
- assert( strcmp( wav_chunk_id_key_list[i].key,<br>
- wav_chunk_id_key_list[i + 1].key ) < 0 );<br>
+ for( size_t i = 0; i < count - 1; ++i )<br>
+ assert( strcmp( id_key_list[i].key,<br>
+ id_key_list[i + 1].key ) < 0 );<br>
#endif<br>
<br>
for( ;; )<br>
@@ -206,8 +279,8 @@ static int ChunkGetNext( demux_t *p_demux, enum wav_chunk_id *p_id,<br>
return VLC_EGENERIC;<br>
<br>
const struct wav_chunk_id_key *id =<br>
- bsearch( p_peek, wav_chunk_id_key_list, wav_chunk_id_key_count,<br>
- sizeof(*wav_chunk_id_key_list), wav_chunk_CompareCb );<br>
+ bsearch( p_peek, id_key_list, count,<br>
+ sizeof(*id_key_list), wav_chunk_CompareCb );<br>
uint32_t i_size = GetDWLE( p_peek + 4 );<br>
<br>
if( id == NULL )<br>
@@ -317,6 +390,10 @@ static void Close ( vlc_object_t * p_this )<br>
demux_sys_t *p_sys = p_demux->p_sys;<br>
<br>
es_format_Clean( &p_sys->fmt );<br>
+<br>
+ if( p_sys->p_meta )<br>
+ vlc_meta_Delete( p_sys->p_meta );<br>
+<br>
free( p_sys );<br>
}<br>
<br>
@@ -591,6 +668,114 @@ error:<br>
return VLC_EGENERIC;<br>
}<br>
<br>
+static int ChunkParseINFO( demux_t *p_demux, uint32_t i_size )<br>
+{<br>
+ demux_sys_t *p_sys = p_demux->p_sys;<br>
+ const uint8_t *p_peek;<br>
+ enum wav_chunk_id id;<br>
+ uint32_t chunk_size;<br>
+ int meta_type;<br>
+ char *meta_value;<br>
+<br>
+ if( (p_sys->p_meta = vlc_meta_New()) == NULL )<br>
+ {<br>
+ msg_Err( p_demux, "vlc_meta_New failed" );<br>
+ return VLC_EGENERIC;<br>
+ }<br>
+<br>
+ while (i_size > 0) {<br>
+ int ret = ChunkGetNext( p_demux, &id, &chunk_size,<br>
+ wav_info_chunk_id_key_list,<br>
+ wav_info_chunk_id_key_count );<br>
+ if ( ret != VLC_SUCCESS )<br>
+ break;<br>
+<br>
+ /* chunk id(4 bytes) and chunk size(4 bytes) consumed by ChunkGetNext */<br>
+ i_size -= 8;<br>
+<br>
+ if( chunk_size == 0 )<br>
+ {<br>
+ msg_Err( p_demux, "invalid chunk with a size 0" );<br>
+ return VLC_EGENERIC;<br>
+ }<br>
+<br>
+ if( vlc_stream_Peek( p_demux->s, &p_peek, chunk_size ) != chunk_size )<br>
+ return VLC_EGENERIC;<br>
+<br>
+ meta_value = strndup( (const char *)p_peek, chunk_size );<br>
+ if (meta_value == NULL)<br>
+ return VLC_EGENERIC;<br>
+<br>
+ EnsureUTF8( meta_value );<br>
+<br>
+ meta_type = -1;<br>
+ switch( id )<br>
+ {<br>
+ case wav_info_chunk_id_iart:<br>
+ meta_type = vlc_meta_Artist;<br>
+ break;<br>
+ case wav_info_chunk_id_icop:<br>
+ meta_type = vlc_meta_Copyright;<br>
+ break;<br>
+ case wav_info_chunk_id_icrd:<br>
+ meta_type = vlc_meta_Date;<br>
+ break;<br>
+ case wav_info_chunk_id_ignr:<br>
+ meta_type = vlc_meta_Genre;<br>
+ break;<br>
+ case wav_info_chunk_id_inam:<br>
+ meta_type = vlc_meta_Title;<br>
+ break;<br>
+ default:<br>
+ /* no relevant meta type in vlc */<br>
+ break;<br>
+ }<br>
+<br>
+ msg_Dbg( p_demux, "id: %s meta_type: %d meta_value: %s\n",<br>
+ wav_info_chunk_id_to_key(id), meta_type, meta_value );<br>
+<br>
+ if (meta_type != -1)<br>
+ vlc_meta_Set( p_sys->p_meta, meta_type, meta_value );<br>
+ else<br>
+ vlc_meta_AddExtra( p_sys->p_meta,<br>
+ wav_info_chunk_id_key_list[id].key, meta_value );<br>
+<br>
+ free( meta_value );<br>
+ if( ChunkSkip( p_demux, chunk_size ) != VLC_SUCCESS )<br>
+ return VLC_EGENERIC;<br>
+<br>
+ i_size -= chunk_size;<br>
+ }<br>
+<br>
+ return VLC_SUCCESS;<br>
+}<br>
+<br>
+static int ChunkParseLIST( demux_t *p_demux, uint32_t i_size )<br>
+{<br>
+ const uint8_t *p_peek;<br>
+<br>
+ /* must have four bytes list type */<br>
+ if( i_size < 4 )<br>
+ {<br>
+ msg_Err( p_demux, "invalid 'LIST' chunk" );<br>
+ return VLC_EGENERIC;<br>
+ }<br>
+<br>
+ if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) != 4 )<br>
+ return VLC_EGENERIC;<br>
+<br>
+ /* only care about INFO chunk */<br>
+ if ( memcmp(p_peek, "INFO", 4) != 0 ) {<br>
+ return ChunkSkip( p_demux, i_size );<br>
+ }<br>
+<br>
+ if ( vlc_stream_Read( p_demux->s, NULL, 4) != 4 )<br>
+ return VLC_EGENERIC;<br>
+<br>
+ i_size -= 4;<br>
+ return ChunkParseINFO( p_demux, i_size );<br>
+}<br>
+<br>
static int Open( vlc_object_t * p_this )<br>
{<br>
demux_t *p_demux = (demux_t*)p_this;<br>
@@ -629,8 +814,13 @@ static int Open( vlc_object_t * p_this )<br>
<br>
bool eof = false;<br>
enum wav_chunk_id id;<br>
- while( !eof && ( ChunkGetNext( p_demux, &id, &i_size ) ) == VLC_SUCCESS )<br>
+ while( !eof )<br>
{<br>
+ int ret = ChunkGetNext( p_demux, &id, &i_size,<br>
+ wav_chunk_id_key_list, wav_chunk_id_key_count );<br>
+ if (ret != VLC_SUCCESS )<br>
+ break;<br>
+<br>
if( i_size == 0 )<br>
{<br>
msg_Err( p_demux, "invalid chunk with a size 0");<br>
@@ -676,6 +866,14 @@ static int Open( vlc_object_t * p_this )<br>
if( ChunkParseFmt( p_demux, i_size ) != VLC_SUCCESS )<br>
goto error;<br>
break;<br>
+ case wav_chunk_id_list:<br>
+ if( ChunkParseLIST( p_demux, i_size ) != VLC_SUCCESS )<br>
+ goto error;<br>
+ break;<br>
+ default:<br>
+ if( ChunkSkip( p_demux, i_size ) != VLC_SUCCESS )<br>
+ goto error;<br>
+ break;<br>
}<br>
}<br>
<br>
-- <br>
2.25.1<br>
<br>
_______________________________________________<br>
vlc-devel mailing list<br>
To unsubscribe or modify your subscription options:<br>
<a href="https://mailman.videolan.org/listinfo/vlc-devel" rel="noreferrer noreferrer" target="_blank">https://mailman.videolan.org/listinfo/vlc-devel</a></blockquote></div>