+/* */
+static void AVI_MetaLoad( demux_t *p_demux,
+ avi_chunk_list_t *p_riff, avi_chunk_avih_t *p_avih )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ vlc_meta_t *p_meta = p_sys->meta = vlc_meta_New();
+ if( !p_meta )
+ return;
+
+ char buffer[200];
+ snprintf( buffer, sizeof(buffer), "%s%s%s%s",
+ p_avih->i_flags&AVIF_HASINDEX ? " HAS_INDEX" : "",
+ p_avih->i_flags&AVIF_MUSTUSEINDEX ? " MUST_USE_INDEX" : "",
+ p_avih->i_flags&AVIF_ISINTERLEAVED ? " IS_INTERLEAVED" : "",
+ p_avih->i_flags&AVIF_TRUSTCKTYPE ? " TRUST_CKTYPE" : "" );
+ vlc_meta_SetSetting( p_meta, buffer );
+
+ avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0 );
+ if( !p_info )
+ return;
+
+ static const struct {
+ vlc_fourcc_t i_id;
+ int i_type;
+ } p_dsc[] = {
+ { AVIFOURCC_IART, vlc_meta_Artist },
+ { AVIFOURCC_ICMT, vlc_meta_Description },
+ { AVIFOURCC_ICOP, vlc_meta_Copyright },
+ { AVIFOURCC_IGNR, vlc_meta_Genre },
+ { AVIFOURCC_INAM, vlc_meta_Title },
+ { 0, -1 }
+ };
+ for( int i = 0; p_dsc[i].i_id != 0; i++ )
+ {
+ avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_dsc[i].i_id, 0 );
+ if( !p_strz )
+ continue;
+ char *psz_value = FromLatin1( p_strz->p_str );
+ if( !psz_value )
+ continue;
+
+ if( *psz_value )
+ vlc_meta_Set( p_meta, p_dsc[i].i_type, psz_value );
+ free( psz_value );
+ }
+}
+
+/*****************************************************************************
+ * Subtitles
+ *****************************************************************************/
+static void AVI_ExtractSubtitle( demux_t *p_demux,
+ int i_stream,
+ avi_chunk_list_t *p_strl,
+ avi_chunk_STRING_t *p_strn )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+ block_t *p_block = NULL;
+ input_attachment_t *p_attachment = NULL;
+ char *psz_description = NULL;
+ avi_chunk_indx_t *p_indx = NULL;
+
+ if( !p_sys->b_seekable )
+ goto exit;
+
+ p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
+ avi_chunk_t ck;
+ int64_t i_position;
+ unsigned i_size;
+ if( p_indx )
+ {
+ if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES &&
+ p_indx->i_entriesinuse > 0 )
+ {
+ if( stream_Seek( p_demux->s, p_indx->idx.super[0].i_offset )||
+ AVI_ChunkRead( p_demux->s, &ck, NULL ) )
+ goto exit;
+ p_indx = &ck.indx;
+ }
+
+ if( p_indx->i_indextype != AVI_INDEX_OF_CHUNKS ||
+ p_indx->i_entriesinuse != 1 ||
+ p_indx->i_indexsubtype != 0 )
+ goto exit;
+
+ i_position = p_indx->i_baseoffset +
+ p_indx->idx.std[0].i_offset - 8;
+ i_size = (p_indx->idx.std[0].i_size & 0x7fffffff) + 8;
+ }
+ else
+ {
+ avi_chunk_idx1_t *p_idx1;
+ uint64_t i_offset;
+
+ if( AVI_IndexFind_idx1( p_demux, &p_idx1, &i_offset ) )
+ goto exit;
+
+ i_size = 0;
+ for( unsigned i = 0; i < p_idx1->i_entry_count; i++ )
+ {
+ const idx1_entry_t *e = &p_idx1->entry[i];
+ unsigned i_cat;
+ unsigned i_stream_idx;
+
+ AVI_ParseStreamHeader( e->i_fourcc, &i_stream_idx, &i_cat );
+ if( i_cat == SPU_ES && i_stream_idx == i_stream )
+ {
+ i_position = e->i_pos + i_offset;
+ i_size = e->i_length + 8;
+ break;
+ }
+ }
+ if( i_size <= 0 )
+ goto exit;
+ }
+
+ /* */
+ if( i_size > 1000000 )
+ goto exit;
+
+ if( stream_Seek( p_demux->s, i_position ) )
+ goto exit;
+ p_block = stream_Block( p_demux->s, i_size );
+ if( !p_block )
+ goto exit;
+
+ /* Parse packet header */
+ const uint8_t *p = p_block->p_buffer;
+ if( i_size < 8 || p[2] != 't' || p[3] != 'x' )
+ goto exit;
+ p += 8;
+ i_size -= 8;
+
+ /* Parse subtitle chunk header */
+ if( i_size < 11 || memcmp( p, "GAB2", 4 ) ||
+ p[4] != 0x00 || GetWLE( &p[5] ) != 0x2 )
+ goto exit;
+ const unsigned i_name = GetDWLE( &p[7] );
+ if( 11 + i_size <= i_name )
+ goto exit;
+ if( i_name > 0 )
+ psz_description = FromCharset( "UTF-16LE", &p[11], i_name );
+ p += 11 + i_name;
+ i_size -= 11 + i_name;
+ if( i_size < 6 || GetWLE( &p[0] ) != 0x04 )
+ goto exit;
+ const unsigned i_payload = GetDWLE( &p[2] );
+ if( i_size < 6 + i_payload || i_payload <= 0 )
+ goto exit;
+ p += 6;
+ i_size -= 6;
+
+ if( !psz_description )
+ psz_description = p_strn ? FromLatin1( p_strn->p_str ) : NULL;
+ char *psz_name;
+ if( asprintf( &psz_name, "subtitle%d.srt", p_sys->i_attachment ) <= 0 )
+ psz_name = NULL;
+ p_attachment = vlc_input_attachment_New( psz_name,
+ "application/x-srt",
+ psz_description,
+ p, i_payload );
+ if( p_attachment )
+ TAB_APPEND( p_sys->i_attachment, p_sys->attachment, p_attachment );
+ free( psz_name );
+
+exit:
+ free( psz_description );
+
+ if( p_block )
+ block_Release( p_block );
+
+ if( p_attachment )
+ msg_Dbg( p_demux, "Loaded an embed subtitle" );
+ else
+ msg_Warn( p_demux, "Failed to load an embed subtitle" );
+
+ if( p_indx == &ck.indx )
+ AVI_ChunkFree( p_demux->s, &ck );
+}