[vlc-commits] demux: mp4: do chan bitmap reordering (fix #12002)

Francois Cartegnie git at videolan.org
Sat Aug 30 05:50:25 CEST 2014


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Aug 27 20:54:46 2014 +0900| [4ed97c5f92a210b651a17e43e705512b86d41d56] | committer: Francois Cartegnie

demux: mp4: do chan bitmap reordering (fix #12002)

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=4ed97c5f92a210b651a17e43e705512b86d41d56
---

 modules/demux/mp4/libmp4.h |   49 +++++++++++++++++++++++++++++++++++
 modules/demux/mp4/mp4.c    |   61 ++++++++++++++++++++++++++++++++++++++++----
 modules/demux/mp4/mp4.h    |    2 ++
 3 files changed, 107 insertions(+), 5 deletions(-)

diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index 1451ce9..d2a5424 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -1038,6 +1038,55 @@ typedef struct
 
 } MP4_Box_data_avcC_t;
 
+/* According to Apple's CoreAudio/CoreAudioTypes.h */
+#define MP4_CHAN_USE_CHANNELS_DESC           0
+#define MP4_CHAN_USE_CHANNELS_BITMAP         (1<<16)
+
+#define MP4_CHAN_BITMAP_LEFT                 (1<<0)
+#define MP4_CHAN_BITMAP_RIGHT                (1<<1)
+#define MP4_CHAN_BITMAP_CENTER               (1<<2)
+#define MP4_CHAN_BITMAP_LFESCREEN            (1<<3)
+#define MP4_CHAN_BITMAP_BACKLEFT             (1<<4)
+#define MP4_CHAN_BITMAP_BACKRIGHT            (1<<5)
+#define MP4_CHAN_BITMAP_LEFTCENTER           (1<<6)
+#define MP4_CHAN_BITMAP_RIGHTCENTER          (1<<7)
+#define MP4_CHAN_BITMAP_BACKCENTER           (1<<8)
+#define MP4_CHAN_BITMAP_SIDELEFT             (1<<9)
+#define MP4_CHAN_BITMAP_SIDERIGHT            (1<<10)
+#define MP4_CHAN_BITMAP_TOPCENTER            (1<<11)
+#define MP4_CHAN_BITMAP_TOPFRONTLEFT         (1<<12)
+#define MP4_CHAN_BITMAP_TOPFRONTENTER        (1<<13)
+#define MP4_CHAN_BITMAP_TOPFRONTRIGHT        (1<<14)
+#define MP4_CHAN_BITMAP_TOPBACKLEFT          (1<<15)
+#define MP4_CHAN_BITMAP_TOPBACKCENTER        (1<<16)
+#define MP4_CHAN_BITMAP_TOPBACKRIGHT         (1<<17)
+
+#define MP4_CHAN_BITMAP_MAPPING_COUNT 18
+static const struct
+{
+    uint32_t i_bitmap;
+    uint32_t i_vlc;
+} chan_bitmap_mapping[MP4_CHAN_BITMAP_MAPPING_COUNT] = {
+    { MP4_CHAN_BITMAP_LEFT,         AOUT_CHAN_LEFT },
+    { MP4_CHAN_BITMAP_RIGHT,        AOUT_CHAN_RIGHT },
+    { MP4_CHAN_BITMAP_CENTER,       AOUT_CHAN_CENTER },
+    { MP4_CHAN_BITMAP_LFESCREEN,    AOUT_CHAN_LFE },
+    { MP4_CHAN_BITMAP_BACKLEFT,     AOUT_CHAN_REARLEFT },
+    { MP4_CHAN_BITMAP_BACKRIGHT,    AOUT_CHAN_REARRIGHT },
+    { MP4_CHAN_BITMAP_LEFTCENTER,   AOUT_CHAN_MIDDLELEFT },
+    { MP4_CHAN_BITMAP_RIGHTCENTER,  AOUT_CHAN_MIDDLERIGHT },
+    { MP4_CHAN_BITMAP_BACKCENTER,   AOUT_CHAN_REARCENTER },
+    { MP4_CHAN_BITMAP_SIDELEFT,     AOUT_CHAN_LEFT },
+    { MP4_CHAN_BITMAP_SIDERIGHT,    AOUT_CHAN_RIGHT },
+    { MP4_CHAN_BITMAP_TOPCENTER,    AOUT_CHAN_CENTER },
+    { MP4_CHAN_BITMAP_TOPFRONTLEFT, AOUT_CHAN_LEFT },
+    { MP4_CHAN_BITMAP_TOPFRONTENTER,AOUT_CHAN_CENTER },
+    { MP4_CHAN_BITMAP_TOPFRONTRIGHT,AOUT_CHAN_RIGHT },
+    { MP4_CHAN_BITMAP_TOPBACKLEFT,  AOUT_CHAN_REARLEFT },
+    { MP4_CHAN_BITMAP_TOPBACKCENTER,AOUT_CHAN_REARCENTER },
+    { MP4_CHAN_BITMAP_TOPBACKRIGHT, AOUT_CHAN_REARRIGHT },
+};
+
 typedef struct
 {
     uint8_t i_version;
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 94fd6d2..cef8be8 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -36,6 +36,7 @@
 #include <vlc_charset.h>                           /* EnsureUTF8 */
 #include <vlc_meta.h>                              /* vlc_meta_t, vlc_meta_ */
 #include <vlc_input.h>
+#include <vlc_aout.h>
 #include <assert.h>
 
 #include "id3genres.h"                             /* for ATOM_gnre */
@@ -114,6 +115,8 @@ static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *, bool b_for
 static int MP4_frg_TrackCreate( demux_t *, mp4_track_t *, MP4_Box_t *);
 static void MP4_TrackDestroy(  mp4_track_t * );
 
+static void MP4_Block_Send( demux_t *, mp4_track_t *, block_t * );
+
 static int  MP4_TrackSelect ( demux_t *, mp4_track_t *, mtime_t );
 static void MP4_TrackUnselect(demux_t *, mp4_track_t * );
 
@@ -388,6 +391,18 @@ static void CreateTracksFromSmooBox( demux_t *p_demux )
     }
 }
 
+static void MP4_Block_Send( demux_t *p_demux, mp4_track_t *p_track, block_t *p_block )
+{
+    if ( p_track->b_chans_reorder && aout_BitsPerSample( p_track->fmt.i_codec ) )
+    {
+        aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
+                             p_track->fmt.audio.i_channels,
+                             p_track->rgi_chans_reordering,
+                             p_track->fmt.i_codec );
+    }
+    es_out_Send( p_demux->out, p_track->p_es, p_block );
+}
+
 /*****************************************************************************
  * Open: check file and initializes MP4 structures
  *****************************************************************************/
@@ -948,7 +963,7 @@ static int Demux( demux_t *p_demux )
             es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr );
             b_data_sent = true;
         }
-        es_out_Send( p_demux->out, tk->p_es, p_block );
+        MP4_Block_Send( p_demux, tk, p_block );
     }
 
     /* Next sample */
@@ -2357,6 +2372,42 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
             msg_Err( p_demux, "Invalid sample per packet value for qt_version 1. Broken muxer!" );
             p_sample->data.p_sample_soun->i_qt_version = 0;
         }
+
+        /* Lookup for then channels extension */
+        const MP4_Box_t *p_chan = MP4_BoxGet( p_sample, "chan" );
+        if ( p_chan )
+        {
+            if ( BOXDATA(p_chan)->layout.i_channels_layout_tag == MP4_CHAN_USE_CHANNELS_BITMAP )
+            {
+                uint32_t rgi_chans_sequence[AOUT_CHAN_MAX + 1];
+                uint16_t i_vlc_mapping = 0;
+                uint8_t i_channels = 0;
+                const uint32_t i_bitmap = BOXDATA(p_chan)->layout.i_channels_bitmap;
+                for (uint8_t i=0;i<MP4_CHAN_BITMAP_MAPPING_COUNT;i++)
+                {
+                    if ( chan_bitmap_mapping[i].i_bitmap & i_bitmap )
+                    {
+                        i_channels++;
+                        if ( (chan_bitmap_mapping[i].i_vlc & i_vlc_mapping) ||
+                             i_channels > AOUT_CHAN_MAX )
+                        {
+                            /* double mapping or unsupported number of channels */
+                            i_vlc_mapping = 0;
+                            msg_Warn( p_demux, "discarding chan mapping" );
+                            break;
+                        }
+                        i_vlc_mapping |= chan_bitmap_mapping[i].i_vlc;
+                        rgi_chans_sequence[i_channels - 1] = chan_bitmap_mapping[i].i_vlc;
+                    }
+                }
+                rgi_chans_sequence[i_channels] = 0;
+                p_track->b_chans_reorder = !!
+                        aout_CheckChannelReorder( rgi_chans_sequence, NULL, i_vlc_mapping,
+                                                  p_track->rgi_chans_reordering );
+            }
+
+        }
+
         break;
 
     default:
@@ -3900,7 +3951,7 @@ static void FlushChunk( demux_t *p_demux, mp4_track_t *tk )
         else
             p_block->i_pts = VLC_TS_INVALID;
 
-        es_out_Send( p_demux->out, tk->p_es, p_block );
+        MP4_Block_Send( p_demux, tk, p_block );
 
         tk->i_sample++;
     }
@@ -4364,7 +4415,7 @@ int DemuxFrg( demux_t *p_demux )
             else
                 p_block->i_pts = VLC_TS_INVALID;
 
-            es_out_Send( p_demux->out, tk->p_es, p_block );
+            MP4_Block_Send( p_demux, tk, p_block );
 
             tk->i_sample++;
 
@@ -4870,7 +4921,7 @@ static int LeafParseTRUN( demux_t *p_demux, mp4_track_t *p_track,
             p_block->i_dts = VLC_TS_0 + i_nzdts;
             p_block->i_pts = VLC_TS_0 + i_nzpts;
             p_block->i_length = CLOCK_FREQ * dur / p_track->i_timescale;
-            es_out_Send( p_demux->out, p_track->p_es, p_block );
+            MP4_Block_Send( p_demux, p_track, p_block );
         }
         else free( p_block );
 
@@ -5111,7 +5162,7 @@ static int LeafParseMDATwithMOOV( demux_t *p_demux )
                 else
                     p_block->i_pts = VLC_TS_INVALID;
 
-                es_out_Send( p_demux->out, p_track->p_es, p_block );
+                MP4_Block_Send( p_demux, p_track, p_block );
 
                 if ( p_demux->p_sys->i_pcr < VLC_TS_0 )
                 {
diff --git a/modules/demux/mp4/mp4.h b/modules/demux/mp4/mp4.h
index 813dfd8..df95de9 100644
--- a/modules/demux/mp4/mp4.h
+++ b/modules/demux/mp4/mp4.h
@@ -73,6 +73,8 @@ typedef struct
     bool b_mac_encoding;
 
     es_format_t fmt;
+    uint8_t     rgi_chans_reordering[AOUT_CHAN_MAX];
+    bool        b_chans_reorder;
     es_out_id_t *p_es;
 
     /* display size only ! */



More information about the vlc-commits mailing list