[vlc-devel] [PATCH 10/24] [dirac] Add demuxer (for raw .drc files) and packetizer

davidf+nntp at woaf.net davidf+nntp at woaf.net
Thu Oct 30 12:29:39 CET 2008


From: David Flynn <davidf at rd.bbc.co.uk>

Bump the demux priority to trump ffmpeg (which currently gets
timestamps wrong)

Signed-off-by: David Flynn <davidf at rd.bbc.co.uk>
---
 modules/demux/Modules.am      |    2 +
 modules/demux/dirac.c         |  172 +++++++++++++++++++
 modules/packetizer/Modules.am |    5 +-
 modules/packetizer/dirac.c    |  380 +++++++++++++++++++++++++++++++++++++++++
 src/input/demux.c             |    1 +
 5 files changed, 559 insertions(+), 1 deletions(-)
 create mode 100644 modules/demux/dirac.c
 create mode 100644 modules/packetizer/dirac.c

diff --git a/modules/demux/Modules.am b/modules/demux/Modules.am
index 72f51fb..e9e6a4a 100644
--- a/modules/demux/Modules.am
+++ b/modules/demux/Modules.am
@@ -30,10 +30,12 @@ SOURCES_vc1 = vc1.c
 SOURCES_demux_cdg = cdg.c
 SOURCES_smf = smf.c
 SOURCES_decomp = decomp.c
+SOURCES_dirac = dirac.c
 
 libvlc_LTLIBRARIES += \
 	libaiff_plugin.la \
 	libau_plugin.la \
+	libdirac_plugin.la \
 	libdemux_cdg_plugin.la \
 	libdemuxdump_plugin.la \
 	libflacsys_plugin.la \
diff --git a/modules/demux/dirac.c b/modules/demux/dirac.c
new file mode 100644
index 0000000..43634f9
--- /dev/null
+++ b/modules/demux/dirac.c
@@ -0,0 +1,172 @@
+/*****************************************************************************
+ * dirac.c : Dirac Video demuxer
+ *****************************************************************************
+ * Copyright (C) 2002-2008 the VideoLAN team
+ * $Id$
+ *
+ * Authors: David Flynn <davidf at rd.bbc.co.uk>
+ * Based on vc1.c by: Laurent Aimar <fenrir at via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_demux.h>
+#include "vlc_codec.h"
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+static int  Open ( vlc_object_t * );
+static void Close( vlc_object_t * );
+
+vlc_module_begin();
+    set_shortname( "Dirac");
+    set_category( CAT_INPUT );
+    set_subcategory( SUBCAT_INPUT_DEMUX );
+    set_description( N_("Dirac video demuxer" ) );
+    set_capability( "demux", 200 );
+    set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+struct demux_sys_t
+{
+    mtime_t     i_dts;
+    es_out_id_t *p_es;
+
+    decoder_t *p_packetizer;
+};
+
+static int Demux( demux_t * );
+static int Control( demux_t *, int, va_list );
+
+#define DIRAC_PACKET_SIZE 4096
+
+/*****************************************************************************
+ * Open: initializes demux 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;
+    es_format_t fmt;
+
+    if( stream_Peek( p_demux->s, &p_peek, 5 ) < 5 ) return VLC_EGENERIC;
+
+    if( p_peek[0] != 'B' || p_peek[1] != 'B' ||
+        p_peek[2] != 'C' || p_peek[3] != 'D') /* start of ParseInfo */
+    {
+        msg_Err( p_demux, "This doesn't look like a Dirac stream (incorrect parsecode)" );
+        if( !p_demux->b_force )
+            return VLC_EGENERIC;
+
+        msg_Warn( p_demux, "continuing anyway" );
+    }
+
+    p_demux->pf_demux  = Demux;
+    p_demux->pf_control= Control;
+    p_demux->p_sys     = p_sys = malloc( sizeof( demux_sys_t ) );
+    p_sys->p_es        = NULL;
+
+    /* Load the packetizer */
+    es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'd','r','a','c' ) );
+    p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "dirac" );
+    if( !p_sys->p_packetizer )
+    {
+        free( p_sys );
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close: frees unused data
+ *****************************************************************************/
+static void Close( vlc_object_t * p_this )
+{
+    demux_t     *p_demux = (demux_t*)p_this;
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    demux_PacketizerDestroy( p_sys->p_packetizer );
+
+    free( p_sys );
+}
+
+/*****************************************************************************
+ * Demux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+static int Demux( demux_t *p_demux)
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    block_t *p_block_in, *p_block_out;
+
+    if( ( p_block_in = stream_Block( p_demux->s, DIRAC_PACKET_SIZE ) ) == NULL )
+        return 0;
+
+    p_block_in->i_dts = p_block_in->i_pts = 0;
+
+    while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in )) )
+    {
+        while( p_block_out )
+        {
+            block_t *p_next = p_block_out->p_next;
+            p_block_out->p_next = NULL;
+
+            if( p_sys->p_es == NULL )
+            {
+                p_sys->p_packetizer->fmt_out.b_packetized = true;
+                p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);
+            }
+
+            es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );
+            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
+
+            p_block_out = p_next;
+        }
+    }
+    return 1;
+}
+
+/*****************************************************************************
+ * Control:
+ *****************************************************************************/
+static int Control( demux_t *p_demux, int i_query, va_list args )
+{
+    /* demux_sys_t *p_sys  = p_demux->p_sys; */
+    /* FIXME calculate the bitrate */
+    if( i_query == DEMUX_SET_TIME )
+        return VLC_EGENERIC;
+    else
+        return demux_vaControlHelper( p_demux->s,
+                                       0, -1,
+                                       0, 1, i_query, args );
+}
+
diff --git a/modules/packetizer/Modules.am b/modules/packetizer/Modules.am
index 7aadef3..2f89ed8 100644
--- a/modules/packetizer/Modules.am
+++ b/modules/packetizer/Modules.am
@@ -4,13 +4,16 @@ SOURCES_packetizer_mpeg4video = mpeg4video.c
 SOURCES_packetizer_mpeg4audio = mpeg4audio.c
 SOURCES_packetizer_h264 = h264.c
 SOURCES_packetizer_vc1 = vc1.c
+SOURCES_packetizer_dirac = dirac.c
 
 libvlc_LTLIBRARIES += \
 	libpacketizer_mpegvideo_plugin.la \
 	libpacketizer_mpeg4video_plugin.la \
 	libpacketizer_mpeg4audio_plugin.la \
 	libpacketizer_h264_plugin.la \
-	libpacketizer_vc1_plugin.la
+	libpacketizer_vc1_plugin.la \
+	libpacketizer_dirac_plugin.la \
+	$(NULL)
 if ENABLE_SOUT
 libvlc_LTLIBRARIES += libpacketizer_copy_plugin.la
 endif
diff --git a/modules/packetizer/dirac.c b/modules/packetizer/dirac.c
new file mode 100644
index 0000000..dd12754
--- /dev/null
+++ b/modules/packetizer/dirac.c
@@ -0,0 +1,380 @@
+/*****************************************************************************
+ * dirac.c
+ *****************************************************************************
+ * Copyright (C) 2008 the VideoLAN team
+ * $Id$
+ *
+ * Authors: David Flynn <davidf at rd.bbc.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+#include <vlc_block.h>
+
+#include "vlc_bits.h"
+#include "vlc_block_helper.h"
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+static int  Open ( vlc_object_t * );
+static void Close( vlc_object_t * );
+
+vlc_module_begin();
+    set_category( CAT_SOUT );
+    set_subcategory( SUBCAT_SOUT_PACKETIZER );
+    set_description( N_("Dirac packetizer") );
+    set_capability( "packetizer", 50 );
+    set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+struct decoder_sys_t
+{
+    /*
+     * Input properties
+     */
+    block_bytestream_t bytestream;
+    int i_state;
+    size_t i_offset;
+    uint32_t u_last_npo;
+
+    date_t m_dts;
+
+    struct seq_hdr_t {
+        uint32_t u_width;
+        uint32_t u_height;
+        uint32_t u_fps_num;
+        uint32_t u_fps_den;
+    } m_seq_hdr;
+
+    /* Current frame being built */
+    block_t    *p_frame;
+    block_t    **pp_last;
+
+    mtime_t i_interpolated_dts;
+};
+
+typedef struct {
+    uint32_t u_next_offset;
+    uint32_t u_prev_offset;
+    int i_parse_code;
+} parse_info_t;
+
+enum {
+    NOT_SYNCED=0,
+    TRY_SYNC,
+    SYNCED,
+    SYNCED_INCOMPLETEDU,
+};
+
+bool dirac_UnpackParseInfo( parse_info_t *p_pi, block_bytestream_t *p_bs, int i_offset );
+static void dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block );
+static block_t *Packetize( decoder_t *p_dec, block_t **pp_block );
+
+/*****************************************************************************
+ * Open: probe the packetizer and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to choose.
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+    decoder_t     *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+
+    if( p_dec->fmt_in.i_codec !=  VLC_FOURCC( 'd','r','a','c' ) )
+        return VLC_EGENERIC;
+
+    p_dec->pf_packetize = Packetize;
+
+    /* Create the output format */
+    es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
+    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
+
+    p_sys->i_state = NOT_SYNCED;
+    p_sys->bytestream = block_BytestreamInit();
+    p_sys->i_offset = 0;
+
+    p_sys->p_frame = NULL;
+    p_sys->pp_last = &p_sys->p_frame;
+
+    p_sys->i_interpolated_dts = -1;
+    date_Init( &p_sys->m_dts, 1, 1);
+
+    if( p_dec->fmt_in.i_extra > 0 )
+    {
+        msg_Err( p_dec, "i_extra > 0 -- no idea why" );
+#if 0
+        block_t *p_init = block_New( p_dec, p_dec->fmt_in.i_extra );
+        block_t *p_pic;
+
+        memcpy( p_init->p_buffer, p_dec->fmt_in.p_extra,
+                p_dec->fmt_in.i_extra );
+
+        while( ( p_pic = Packetize( p_dec, &p_init ) ) )
+            block_Release( p_pic ); /* Should not happen (only sequence header) */
+#endif
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+    decoder_t     *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    block_BytestreamRelease( &p_sys->bytestream );
+    if( p_sys->p_frame )
+        block_Release( p_sys->p_frame );
+    free( p_sys );
+}
+
+/*****************************************************************************
+ * Packetize: packetize an access unit
+ *****************************************************************************/
+static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t       *p_pic;
+
+    if( pp_block == NULL || *pp_block == NULL )
+        return NULL;
+
+    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
+    {
+        /* don't think this is right XXX */
+        if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
+        {
+            p_sys->i_state = NOT_SYNCED;
+            block_BytestreamFlush( &p_sys->bytestream );
+
+            if( p_sys->p_frame )
+                block_ChainRelease( p_sys->p_frame );
+            p_sys->p_frame = NULL;
+            p_sys->pp_last = &p_sys->p_frame;
+        }
+        block_Release( *pp_block );
+        return NULL;
+    }
+
+    block_BytestreamPush( &p_sys->bytestream, *pp_block );
+    *pp_block = NULL;
+
+    parse_info_t pu;
+
+    static const uint8_t p_parsecode[4] = {'B','B','C','D'};
+    do {
+        switch( p_sys->i_state )
+        {
+        case NOT_SYNCED:
+            /* shouldn't try sync if there isn't a whole PI avaliable */
+            /* or, rather, if we found a sync, ignore it if it is close to the end */
+            if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_parsecode, 4 ) != VLC_SUCCESS ) {
+                return NULL; /* goto cleanup */
+            }
+        case TRY_SYNC: { /* -> SYNCED | NOT_SYNCED */
+            parse_info_t pu1;
+            bool a = dirac_UnpackParseInfo(&pu1, &p_sys->bytestream, p_sys->i_offset);
+            bool b = dirac_UnpackParseInfo(&pu, &p_sys->bytestream, p_sys->i_offset - pu1.u_prev_offset);
+            if( !a || !b || (pu1.u_prev_offset != pu.u_next_offset) ) {
+                p_sys->i_state = NOT_SYNCED;
+                p_sys->i_offset++;
+                break; /* find somewhere else to try again */
+            }
+            p_sys->u_last_npo = pu.u_next_offset;
+            p_sys->i_offset -= pu.u_next_offset;
+            p_sys->i_state = SYNCED;
+            break;
+        }
+        case SYNCED: { /* -> SYNCED | NOT_SYNCED */
+            bool a = dirac_UnpackParseInfo(&pu, &p_sys->bytestream, p_sys->i_offset);
+            if (!a || (p_sys->u_last_npo != pu.u_prev_offset)) {
+                p_sys->i_state = NOT_SYNCED;
+                break;
+            }
+            //p_sys->i_offset += pu.u_next_offset;
+            p_sys->u_last_npo = pu.u_next_offset;
+            p_sys->i_state = SYNCED;
+            break;
+        }
+        case SYNCED_INCOMPLETEDU: /* -> SYNCED */
+            dirac_UnpackParseInfo(&pu, &p_sys->bytestream, p_sys->i_offset );
+            p_sys->i_state = SYNCED; /* try again */
+        }
+    } while( NOT_SYNCED == p_sys->i_state );
+
+    /* synced, attempt to extract a data unit */
+    /* if we can't peek at the last byte, we don't yet have the entire DU */
+    if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_offset + pu.u_next_offset, NULL, 0) ) {
+        p_sys->i_state = SYNCED_INCOMPLETEDU;
+        return NULL;
+    }
+
+    /* flush everything upto the start of the DU */
+    block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
+    block_BytestreamFlush( &p_sys->bytestream );
+    p_sys->i_offset = 0;
+    /* copy the DU and insert into the output chain */
+    p_pic = block_New( p_dec, pu.u_next_offset );
+    block_GetBytes( &p_sys->bytestream, p_pic->p_buffer, p_pic->i_buffer );
+    block_ChainLastAppend( &p_sys->pp_last, p_pic );
+
+    if( 0x08 & p_pic->p_buffer[4] ) {
+        /* p_pic is a picture -- it ends the 'mux unit' */
+        /* this isn't possible if no seq hdr has been found yet */
+        uint32_t u_picnum = GetDWBE( p_pic->p_buffer + 13 );
+        date_t pts;
+        date_Init( &pts, p_sys->m_seq_hdr.u_fps_num, p_sys->m_seq_hdr.u_fps_den );
+        //p_pic->i_flags = BLOCK_FLAG_TYPE_I
+
+        p_pic = block_ChainGather( p_sys->p_frame );
+        p_sys->p_frame = NULL;
+        p_sys->pp_last = &p_sys->p_frame;
+
+        p_pic->i_pts = date_Increment( &pts, u_picnum );
+        p_pic->i_dts = date_Get( &p_sys->m_dts );
+        date_Increment( &p_sys->m_dts, 3);
+
+        p_pic->i_dts =
+        p_pic->i_pts = u_picnum * INT64_C(1000000) / ((float) p_sys->m_seq_hdr.u_fps_num / p_sys->m_seq_hdr.u_fps_den);
+    }
+    else if( 0 == p_pic->p_buffer[4] ) {
+        /* we should stash a copy of this -- it isn't allowed to change ever */
+        dirac_UnpackSeqHdr(&p_sys->m_seq_hdr, p_pic);
+
+        es_format_t *p_es = &p_dec->fmt_out;
+#if 0
+        p_es->video.i_width  = p_sys->m_seq_hdr.u_width;
+        p_es->video.i_height = p_sys->m_seq_hdr.u_height;
+#endif
+        vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base
+                   , p_sys->m_seq_hdr.u_fps_num, p_sys->m_seq_hdr.u_fps_den, 0 );
+
+        date_Change( &p_sys->m_dts, p_sys->m_seq_hdr.u_fps_num, p_sys->m_seq_hdr.u_fps_den );
+
+        p_pic = NULL;
+    }
+    else {
+        p_pic = NULL;
+    }
+    return p_pic;
+}
+
+
+bool dirac_UnpackParseInfo( parse_info_t *p_pi, block_bytestream_t *p_bs, int i_offset )
+{
+    if (i_offset < 0)
+        return false;
+
+    uint8_t p_d[13];
+    if( VLC_SUCCESS != block_PeekOffsetBytes( p_bs, i_offset, p_d, 13) ) {
+        return false;
+    }
+
+    if (p_d[0] != 'B' || p_d[1] != 'B' || p_d[2] != 'C' || p_d[3] != 'D')
+        return false;
+
+    p_pi->i_parse_code = p_d[4];
+    p_pi->u_next_offset = p_d[5] << 24 | p_d[6] << 16 | p_d[7] << 8 | p_d[8];
+    p_pi->u_prev_offset = p_d[9] << 24 | p_d[10] << 16 | p_d[11] << 8 | p_d[12];
+    return true;
+}
+
+static uint32_t dirac_uint( bs_t *p_bs )
+{
+  uint32_t count = 0, value = 0;
+  while( !bs_read( p_bs, 1 ) ) {
+    count++;
+    value <<= 1;
+    value |= bs_read ( p_bs, 1 );
+  }
+
+  return (1<<count) - 1 + value;
+}
+
+static int dirac_bool( bs_t *p_bs )
+{
+    return bs_read( p_bs, 1 );
+}
+
+/* read in useful bits from sequence header */
+static void dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block )
+{
+    bs_t bs;
+    bs_init( &bs, p_block->p_buffer, p_block->i_buffer );
+    bs_skip( &bs, 13*8); /* parse_info_header */
+    dirac_uint( &bs ); /* major_version */
+    dirac_uint( &bs ); /* minor_version */
+    dirac_uint( &bs ); /* profile */
+    dirac_uint( &bs ); /* level */
+
+    uint32_t u_video_format = dirac_uint( &bs ); /* index */
+
+    if (dirac_bool( &bs )) {
+        dirac_uint( &bs ); /* frame_width */
+        dirac_uint( &bs ); /* frame_height */
+    }
+
+    if (dirac_bool( &bs )) {
+        dirac_uint( &bs ); /* chroma_format */
+    }
+    if (dirac_bool( &bs )) {
+        if (dirac_bool( &bs )) { /* interlaced */
+            dirac_bool( &bs ); /* top_field_first */
+        }
+    }
+
+    static const struct {
+        uint32_t u_n /* numerator */, u_d /* denominator */;
+    } dirac_frate_tbl[] = { /* table 10.3 */
+        {1, 1}, /* this value is not used */
+        {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
+        {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
+    };
+
+    static const uint32_t dirac_vidfmt_frate[] = { /* table C.1 */
+        1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
+    };
+
+    p_sh->u_fps_num = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_n;
+    p_sh->u_fps_den = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_d;
+    if (dirac_bool( &bs )) {
+        uint32_t frame_rate_index = dirac_uint( &bs );
+        p_sh->u_fps_num = dirac_frate_tbl[frame_rate_index].u_n;
+        p_sh->u_fps_den = dirac_frate_tbl[frame_rate_index].u_d;
+        if (frame_rate_index == 0) {
+            p_sh->u_fps_num = dirac_uint( &bs ); /* frame_rate_numerator */
+            p_sh->u_fps_den = dirac_uint( &bs ); /* frame_rate_denominator */
+        }
+    }
+}
diff --git a/src/input/demux.c b/src/input/demux.c
index 9d51e6a..5ab1e2b 100644
--- a/src/input/demux.c
+++ b/src/input/demux.c
@@ -97,6 +97,7 @@ demux_t *__demux_New( vlc_object_t *p_obj,
             { "au",   "au" },
             { "flac", "flac" },
             { "dv",   "dv" },
+            { "drc",  "dirac" },
             { "m3u",  "playlist" },
             { "mkv",  "mkv" }, { "mka",  "mkv" }, { "mks",  "mkv" },
             { "mp4",  "mp4" }, { "m4a",  "mp4" }, { "mov",  "mp4" }, { "moov", "mp4" },
-- 
1.5.6.5




More information about the vlc-devel mailing list