[vlc-devel] [PATCH 08/17] a52: move to packetizer

Thomas Guillem thomas at gllm.fr
Wed Jul 27 17:27:24 CEST 2016


---
 extras/package/rpm/vlc.altlinux.spec |   3 +-
 modules/codec/Makefile.am            |   3 -
 modules/codec/a52.c                  | 430 -----------------------------------
 modules/codec/a52.h                  | 216 ------------------
 modules/demux/mpeg/es.c              |   2 +-
 modules/packetizer/Makefile.am       |   3 +-
 modules/packetizer/a52.c             | 328 ++++++++++++++++++++++++++
 modules/packetizer/a52.h             | 216 ++++++++++++++++++
 po/POTFILES.in                       |   2 +-
 9 files changed, 549 insertions(+), 654 deletions(-)
 delete mode 100644 modules/codec/a52.c
 delete mode 100644 modules/codec/a52.h
 create mode 100644 modules/packetizer/a52.c
 create mode 100644 modules/packetizer/a52.h

diff --git a/extras/package/rpm/vlc.altlinux.spec b/extras/package/rpm/vlc.altlinux.spec
index 33511ad..021ca24 100644
--- a/extras/package/rpm/vlc.altlinux.spec
+++ b/extras/package/rpm/vlc.altlinux.spec
@@ -1033,7 +1033,6 @@ strfile %buildroot%_gamesdatadir/fortune/vlc %buildroot%_gamesdatadir/fortune/vl
 %_vlc_pluginsdir/audio_output/libaout_file_plugin.so*
 
 %dir %_vlc_pluginsdir/codec
-%_vlc_pluginsdir/codec/liba52_plugin.so*
 %_vlc_pluginsdir/codec/libadpcm_plugin.so*
 %_vlc_pluginsdir/codec/libaraw_plugin.so*
 %_vlc_pluginsdir/codec/librawvideo_plugin.so*
@@ -1135,7 +1134,7 @@ strfile %buildroot%_gamesdatadir/fortune/vlc %buildroot%_gamesdatadir/fortune/vl
 #%_vlc_pluginsdir/mux/libmux_ts_plugin.so*
 
 %dir %_vlc_pluginsdir/packetizer
-#_vlc_pluginsdir/packetizer/libpacketizer_a52_plugin.so*
+%_vlc_pluginsdir/packetizer/libpacketizer_a52_plugin.so*
 %_vlc_pluginsdir/packetizer/libpacketizer_copy_plugin.so*
 %_vlc_pluginsdir/packetizer/libpacketizer_mpeg4audio_plugin.so*
 %_vlc_pluginsdir/packetizer/libpacketizer_mpeg4video_plugin.so*
diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index 6703091..ef0aa74 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -16,9 +16,6 @@ endif
 libspdif_plugin_la_SOURCES = codec/spdif.c
 codec_LTLIBRARIES += libspdif_plugin.la
 
-liba52_plugin_la_SOURCES = codec/a52.c codec/a52.h
-codec_LTLIBRARIES += liba52_plugin.la
-
 libadpcm_plugin_la_SOURCES = codec/adpcm.c
 codec_LTLIBRARIES += libadpcm_plugin.la
 
diff --git a/modules/codec/a52.c b/modules/codec/a52.c
deleted file mode 100644
index 044905b..0000000
--- a/modules/codec/a52.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*****************************************************************************
- * a52.c: parse A/52 audio sync info and packetize the stream
- *****************************************************************************
- * Copyright (C) 2001-2002 VLC authors and VideoLAN
- * $Id$
- *
- * Authors: Stéphane Borel <stef at via.ecp.fr>
- *          Christophe Massiot <massiot at via.ecp.fr>
- *          Gildas Bazin <gbazin at videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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_helper.h>
-#include <vlc_modules.h>
-
-#include "a52.h"
-
-#include "../packetizer/packetizer_helper.h"
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-static int  OpenDecoder   ( vlc_object_t * );
-static int  OpenPacketizer( vlc_object_t * );
-static void CloseCommon   ( vlc_object_t * );
-
-vlc_module_begin ()
-    set_description( N_("A/52 parser") )
-    set_capability( "decoder", 100 )
-    set_callbacks( OpenDecoder, CloseCommon )
-    set_category( CAT_INPUT )
-    set_subcategory( SUBCAT_INPUT_ACODEC )
-
-    add_submodule ()
-    set_description( N_("A/52 audio packetizer") )
-    set_capability( "packetizer", 10 )
-    set_callbacks( OpenPacketizer, CloseCommon )
-vlc_module_end ()
-
-/*****************************************************************************
- * decoder_sys_t : decoder descriptor
- *****************************************************************************/
-
-struct decoder_sys_t
-{
-    /* Module mode */
-    bool b_packetizer;
-
-    /*
-     * Input properties
-     */
-    int i_state;
-
-    block_bytestream_t bytestream;
-
-    /*
-     * Common properties
-     */
-    date_t  end_date;
-
-    mtime_t i_pts;
-
-    vlc_a52_header_t frame;
-};
-
-/****************************************************************************
- * Local prototypes
- ****************************************************************************/
-static block_t *DecodeBlock  ( decoder_t *, block_t ** );
-static void Flush( decoder_t * );
-
-static uint8_t *GetOutBuffer ( decoder_t *, block_t ** );
-static block_t *GetAoutBuffer( decoder_t * );
-static block_t *GetSoutBuffer( decoder_t * );
-
-/*****************************************************************************
- * OpenCommon: probe the decoder/packetizer and return score
- *****************************************************************************/
-static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
-{
-    decoder_t *p_dec = (decoder_t*)p_this;
-    decoder_sys_t *p_sys;
-    vlc_fourcc_t i_codec;
-
-    switch( p_dec->fmt_in.i_codec )
-    {
-    case VLC_CODEC_A52:
-        i_codec = VLC_CODEC_A52;
-        break;
-    case VLC_CODEC_EAC3:
-        /* XXX ugly hack, a52 does not support eac3 so no eac3 pass-through
-         * support */
-        if( !b_packetizer )
-            return VLC_EGENERIC;
-        i_codec = VLC_CODEC_EAC3;
-        break;
-    default:
-        return VLC_EGENERIC;
-    }
-
-    /* Allocate the memory needed to store the decoder's structure */
-    if( ( p_dec->p_sys = p_sys =
-          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
-        return VLC_ENOMEM;
-
-    /* Misc init */
-    p_sys->b_packetizer = b_packetizer;
-    p_sys->i_state = STATE_NOSYNC;
-    date_Set( &p_sys->end_date, 0 );
-    p_sys->i_pts = VLC_TS_INVALID;
-
-    block_BytestreamInit( &p_sys->bytestream );
-
-    /* Set output properties */
-    p_dec->fmt_out.i_cat = AUDIO_ES;
-    p_dec->fmt_out.i_codec = i_codec;
-    p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
-    p_dec->fmt_out.audio.i_bytes_per_frame = 0;
-
-    /* Set callback */
-    if( b_packetizer )
-        p_dec->pf_packetize    = DecodeBlock;
-    else
-        p_dec->pf_decode_audio = DecodeBlock;
-    p_dec->pf_flush            = Flush;
-    return VLC_SUCCESS;
-}
-
-static int OpenDecoder( vlc_object_t *p_this )
-{
-    /* HACK: Don't use this codec if we don't have an a52 audio filter */
-    if( !module_exists( "a52tofloat32" ) )
-        return VLC_EGENERIC;
-    return OpenCommon( p_this, false );
-}
-
-static int OpenPacketizer( vlc_object_t *p_this )
-{
-    return OpenCommon( p_this, true );
-}
-
-/*****************************************************************************
- * Flush:
- *****************************************************************************/
-static void Flush( decoder_t *p_dec )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    date_Set( &p_sys->end_date, 0 );
-    p_sys->i_state = STATE_NOSYNC;
-    block_BytestreamEmpty( &p_sys->bytestream );
-}
-
-/****************************************************************************
- * DecodeBlock: the whole thing
- ****************************************************************************
- * This function is called just after the thread is launched.
- ****************************************************************************/
-static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    uint8_t p_header[VLC_A52_HEADER_SIZE];
-    uint8_t *p_buf;
-    block_t *p_out_buffer;
-
-    if( !pp_block || !*pp_block ) return NULL;
-
-    if( (*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
-    {
-        if( (*pp_block)->i_flags & BLOCK_FLAG_CORRUPTED )
-        {
-            Flush( p_dec );
-            block_Release( *pp_block );
-            *pp_block = NULL;
-            return NULL;
-        }
-        else /* BLOCK_FLAG_DISCONTINUITY */
-            date_Set( &p_sys->end_date, 0 );
-
-    }
-
-    if( !date_Get( &p_sys->end_date ) && (*pp_block)->i_pts <= VLC_TS_INVALID)
-    {
-        /* We've just started the stream, wait for the first PTS. */
-        block_Release( *pp_block );
-        *pp_block = NULL;
-        return NULL;
-    }
-
-    block_BytestreamPush( &p_sys->bytestream, *pp_block );
-
-    while( 1 )
-    {
-        switch( p_sys->i_state )
-        {
-        case STATE_NOSYNC:
-            while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
-                   == VLC_SUCCESS )
-            {
-                if( p_header[0] == 0x0b && p_header[1] == 0x77 )
-                {
-                    p_sys->i_state = STATE_SYNC;
-                    break;
-                }
-                block_SkipByte( &p_sys->bytestream );
-            }
-            if( p_sys->i_state != STATE_SYNC )
-            {
-                block_BytestreamFlush( &p_sys->bytestream );
-
-                /* Need more data */
-                return NULL;
-            }
-
-        case STATE_SYNC:
-            /* New frame, set the Presentation Time Stamp */
-            p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
-            if( p_sys->i_pts > VLC_TS_INVALID &&
-                p_sys->i_pts != date_Get( &p_sys->end_date ) )
-            {
-                date_Set( &p_sys->end_date, p_sys->i_pts );
-            }
-            p_sys->i_state = STATE_HEADER;
-
-        case STATE_HEADER:
-            /* Get A/52 frame header (VLC_A52_HEADER_SIZE bytes) */
-            if( block_PeekBytes( &p_sys->bytestream, p_header,
-                                 VLC_A52_HEADER_SIZE ) != VLC_SUCCESS )
-            {
-                /* Need more data */
-                return NULL;
-            }
-
-            /* Check if frame is valid and get frame info */
-            if( vlc_a52_header_Parse( &p_sys->frame, p_header, VLC_A52_HEADER_SIZE ) )
-            {
-                msg_Dbg( p_dec, "emulated sync word" );
-                block_SkipByte( &p_sys->bytestream );
-                p_sys->i_state = STATE_NOSYNC;
-                break;
-            }
-
-            p_sys->i_state = STATE_NEXT_SYNC;
-
-        case STATE_NEXT_SYNC:
-            /* TODO: If pp_block == NULL, flush the buffer without checking the
-             * next sync word */
-
-            /* Check if next expected frame contains the sync word */
-            if( block_PeekOffsetBytes( &p_sys->bytestream,
-                                       p_sys->frame.i_size, p_header, 2 )
-                != VLC_SUCCESS )
-            {
-                /* Need more data */
-                return NULL;
-            }
-
-            if( p_sys->b_packetizer &&
-                p_header[0] == 0 && p_header[1] == 0 )
-            {
-                /* A52 wav files and audio CD's use stuffing */
-                p_sys->i_state = STATE_GET_DATA;
-                break;
-            }
-
-            if( p_header[0] != 0x0b || p_header[1] != 0x77 )
-            {
-                msg_Dbg( p_dec, "emulated sync word "
-                         "(no sync on following frame)" );
-                p_sys->i_state = STATE_NOSYNC;
-                block_SkipByte( &p_sys->bytestream );
-                break;
-            }
-            p_sys->i_state = STATE_SEND_DATA;
-            break;
-
-        case STATE_GET_DATA:
-            /* Make sure we have enough data.
-             * (Not useful if we went through NEXT_SYNC) */
-            if( block_WaitBytes( &p_sys->bytestream,
-                                 p_sys->frame.i_size ) != VLC_SUCCESS )
-            {
-                /* Need more data */
-                return NULL;
-            }
-            p_sys->i_state = STATE_SEND_DATA;
-
-        case STATE_SEND_DATA:
-            if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
-            {
-                //p_dec->b_error = true;
-                return NULL;
-            }
-
-            /* Copy the whole frame into the buffer. When we reach this point
-             * we already know we have enough data available. */
-            block_GetBytes( &p_sys->bytestream,
-                            p_buf, __MIN( p_sys->frame.i_size, p_out_buffer->i_buffer ) );
-
-            /* Make sure we don't reuse the same pts twice */
-            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
-                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;
-
-            /* So p_block doesn't get re-added several times */
-            *pp_block = block_BytestreamPop( &p_sys->bytestream );
-
-            p_sys->i_state = STATE_NOSYNC;
-
-            return p_out_buffer;
-        }
-    }
-}
-
-/*****************************************************************************
- * CloseCommon: clean up the decoder
- *****************************************************************************/
-static void CloseCommon( 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 );
-
-    free( p_sys );
-}
-
-/*****************************************************************************
- * GetOutBuffer:
- *****************************************************************************/
-static uint8_t *GetOutBuffer( decoder_t *p_dec, block_t **pp_out_buffer )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    uint8_t *p_buf;
-
-    if( p_dec->fmt_out.audio.i_rate != p_sys->frame.i_rate )
-    {
-        msg_Dbg( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
-                 p_sys->frame.i_channels, p_sys->frame.i_rate, p_sys->frame.i_bitrate );
-
-        date_Init( &p_sys->end_date, p_sys->frame.i_rate, 1 );
-        date_Set( &p_sys->end_date, p_sys->i_pts );
-    }
-
-    p_dec->fmt_out.audio.i_rate     = p_sys->frame.i_rate;
-    p_dec->fmt_out.audio.i_channels = p_sys->frame.i_channels;
-    if( p_dec->fmt_out.audio.i_bytes_per_frame < p_sys->frame.i_size )
-        p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->frame.i_size;
-    p_dec->fmt_out.audio.i_frame_length = p_sys->frame.i_samples;
-
-    p_dec->fmt_out.audio.i_original_channels = p_sys->frame.i_channels_conf;
-    p_dec->fmt_out.audio.i_physical_channels =
-        p_sys->frame.i_channels_conf & AOUT_CHAN_PHYSMASK;
-
-    p_dec->fmt_out.i_bitrate = p_sys->frame.i_bitrate;
-
-    if( p_sys->b_packetizer )
-    {
-        block_t *p_sout_buffer = GetSoutBuffer( p_dec );
-        p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
-        *pp_out_buffer = p_sout_buffer;
-    }
-    else
-    {
-        block_t *p_aout_buffer = GetAoutBuffer( p_dec );
-        p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
-        *pp_out_buffer = p_aout_buffer;
-    }
-
-    return p_buf;
-}
-
-/*****************************************************************************
- * GetAoutBuffer:
- *****************************************************************************/
-static block_t *GetAoutBuffer( decoder_t *p_dec )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    block_t *p_buf = decoder_NewAudioBuffer( p_dec, p_sys->frame.i_samples );
-    if( p_buf )
-    {
-        p_buf->i_pts = date_Get( &p_sys->end_date );
-        p_buf->i_length = date_Increment( &p_sys->end_date,
-                                          p_sys->frame.i_samples ) - p_buf->i_pts;
-    }
-
-    return p_buf;
-}
-
-/*****************************************************************************
- * GetSoutBuffer:
- *****************************************************************************/
-static block_t *GetSoutBuffer( decoder_t *p_dec )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    block_t *p_block = block_Alloc( p_sys->frame.i_size );
-    if( p_block )
-    {
-        p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
-        p_block->i_length =
-            date_Increment( &p_sys->end_date, p_sys->frame.i_samples ) - p_block->i_pts;
-    }
-
-    return p_block;
-}
-
diff --git a/modules/codec/a52.h b/modules/codec/a52.h
deleted file mode 100644
index 3b7315c..0000000
--- a/modules/codec/a52.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*****************************************************************************
- * a52.h
- *****************************************************************************
- * Copyright (C) 2001-2009 Laurent Aimar
- * $Id$
- *
- * Authors: Stéphane Borel <stef at via.ecp.fr>
- *          Christophe Massiot <massiot at via.ecp.fr>
- *          Gildas Bazin <gbazin at videolan.org>
- *          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 Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *****************************************************************************/
-
-#ifndef VLC_A52_H_
-#define VLC_A52_H_
-
-#include <vlc_bits.h>
-
-/**
- * Minimum AC3 header size that vlc_a52_header_Parse needs.
- */
-#define VLC_A52_HEADER_SIZE (8)
-
-/**
- * AC3 header information.
- */
-typedef struct
-{
-    bool b_eac3;
-
-    unsigned int i_channels;
-    unsigned int i_channels_conf;
-    unsigned int i_rate;
-    unsigned int i_bitrate;
-
-    unsigned int i_size;
-    unsigned int i_samples;
-
-} vlc_a52_header_t;
-
-/**
- * It parse AC3 sync info.
- *
- * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
- * since we don't want to oblige S/PDIF people to use liba52 just to get
- * their SyncInfo...
- */
-static inline int vlc_a52_header_ParseAc3( vlc_a52_header_t *p_header,
-                                           const uint8_t *p_buf,
-                                           const uint32_t *p_acmod )
-{
-    static const uint8_t pi_halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
-    static const unsigned int pi_bitrate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
-                                128, 160, 192, 224, 256, 320, 384, 448,
-                                512, 576, 640 };
-    static const uint8_t pi_lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
-                                      0x04, 0x01, 0x04, 0x01 };
-
-    /* */
-    const unsigned i_rate_shift = pi_halfrate[p_buf[5] >> 3];
-
-    /* acmod, dsurmod and lfeon */
-    const unsigned i_acmod = p_buf[6] >> 5;
-    if( (p_buf[6] & 0xf8) == 0x50 )
-        /* Dolby surround = stereo + Dolby */
-        p_header->i_channels_conf = AOUT_CHANS_STEREO | AOUT_CHAN_DOLBYSTEREO;
-    else
-        p_header->i_channels_conf = p_acmod[i_acmod];
-    if( p_buf[6] & pi_lfeon[i_acmod] )
-        p_header->i_channels_conf |= AOUT_CHAN_LFE;
-
-    p_header->i_channels = popcount(p_header->i_channels_conf
-                                                         & AOUT_CHAN_PHYSMASK);
-
-    const unsigned i_frmsizecod = p_buf[4] & 63;
-    if( i_frmsizecod >= 38 )
-        return VLC_EGENERIC;
-    const unsigned i_bitrate_base = pi_bitrate[i_frmsizecod >> 1];
-    p_header->i_bitrate = (i_bitrate_base * 1000) >> i_rate_shift;
-
-    switch( p_buf[4] & 0xc0 )
-    {
-    case 0:
-        p_header->i_rate = 48000 >> i_rate_shift;
-        p_header->i_size = 4 * i_bitrate_base;
-        break;
-    case 0x40:
-        p_header->i_rate = 44100 >> i_rate_shift;
-        p_header->i_size = 2 * (320 * i_bitrate_base / 147 + (i_frmsizecod & 1));
-        break;
-    case 0x80:
-        p_header->i_rate = 32000 >> i_rate_shift;
-        p_header->i_size = 6 * i_bitrate_base;
-        break;
-    default:
-        return VLC_EGENERIC;
-    }
-    p_header->i_samples = 6*256;
-
-    p_header->b_eac3 = false;
-    return VLC_SUCCESS;
-}
-
-/**
- * It parse E-AC3 sync info
- */
-static inline int vlc_a52_header_ParseEac3( vlc_a52_header_t *p_header,
-                                            const uint8_t *p_buf,
-                                            const uint32_t *p_acmod )
-{
-    static const unsigned pi_samplerate[3] = { 48000, 44100, 32000 };
-    unsigned i_numblkscod;
-    bs_t s;
-
-
-    bs_init( &s, (void*)p_buf, VLC_A52_HEADER_SIZE );
-    bs_skip( &s, 16 +   /* start code */
-                 2 +    /* stream type */
-                 3 );   /* substream id */
-    const unsigned i_frame_size = bs_read( &s, 11 );
-    if( i_frame_size < 2 )
-        return VLC_EGENERIC;
-    p_header->i_size = 2 * ( i_frame_size + 1 );
-
-    const unsigned i_fscod = bs_read( &s, 2 );
-    if( i_fscod == 0x03 )
-    {
-        const unsigned i_fscod2 = bs_read( &s, 2 );
-        if( i_fscod2 == 0X03 )
-            return VLC_EGENERIC;
-        p_header->i_rate = pi_samplerate[i_fscod2] / 2;
-        i_numblkscod = 6;
-    }
-    else
-    {
-        static const int pi_blocks[4] = { 1, 2, 3, 6 };
-
-        p_header->i_rate = pi_samplerate[i_fscod];
-        i_numblkscod = pi_blocks[bs_read( &s, 2 )];
-    }
-
-    const unsigned i_acmod = bs_read( &s, 3 );
-    const unsigned i_lfeon = bs_read1( &s );
-
-    p_header->i_channels_conf = p_acmod[i_acmod];
-    if( i_lfeon )
-        p_header->i_channels_conf |= AOUT_CHAN_LFE;
-    p_header->i_channels = popcount(p_header->i_channels_conf
-                                                         & AOUT_CHAN_PHYSMASK);
-    p_header->i_bitrate = 8 * p_header->i_size * (p_header->i_rate)
-                                               / (i_numblkscod * 256);
-    p_header->i_samples = i_numblkscod * 256;
-
-    p_header->b_eac3 = true;
-    return VLC_SUCCESS;
-}
-
-/**
- * It will parse the header AC3 frame and fill vlc_a52_header_t* if
- * it is valid or return VLC_EGENERIC.
- *
- * XXX It will only recognize big endian bitstream ie starting with 0x0b, 0x77
- */
-static inline int vlc_a52_header_Parse( vlc_a52_header_t *p_header,
-                                        const uint8_t *p_buffer, int i_buffer )
-{
-    static const uint32_t p_acmod[8] = {
-        AOUT_CHANS_2_0 | AOUT_CHAN_DUALMONO,
-        AOUT_CHAN_CENTER,
-        AOUT_CHANS_2_0,
-        AOUT_CHANS_3_0,
-        AOUT_CHANS_FRONT | AOUT_CHAN_REARCENTER, /* 2F1R */
-        AOUT_CHANS_FRONT | AOUT_CHANS_CENTER,    /* 3F1R */
-        AOUT_CHANS_4_0,
-        AOUT_CHANS_5_0,
-    };
-
-    if( i_buffer < VLC_A52_HEADER_SIZE )
-        return VLC_EGENERIC;
-
-    /* Check synword */
-    if( p_buffer[0] != 0x0b || p_buffer[1] != 0x77 )
-        return VLC_EGENERIC;
-
-    /* Check bsid */
-    const int bsid = p_buffer[5] >> 3;
-    if( bsid > 16 )
-        return VLC_EGENERIC;
-
-    if( bsid <= 10 )
-    {
-        if( vlc_a52_header_ParseAc3( p_header, p_buffer, p_acmod ) )
-            return VLC_EGENERIC;
-    }
-    else
-    {
-        if( vlc_a52_header_ParseEac3( p_header, p_buffer, p_acmod ) )
-            return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
-
-#endif
diff --git a/modules/demux/mpeg/es.c b/modules/demux/mpeg/es.c
index ba80bb7..69785be 100644
--- a/modules/demux/mpeg/es.c
+++ b/modules/demux/mpeg/es.c
@@ -37,7 +37,7 @@
 #include <vlc_codecs.h>
 #include <vlc_input.h>
 
-#include "../../codec/a52.h"
+#include "../../packetizer/a52.h"
 #include "../../codec/dts_header.h"
 
 /*****************************************************************************
diff --git a/modules/packetizer/Makefile.am b/modules/packetizer/Makefile.am
index 42edf1f..2bc1190 100644
--- a/modules/packetizer/Makefile.am
+++ b/modules/packetizer/Makefile.am
@@ -16,6 +16,7 @@ libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c \
 	packetizer/hevc_nal.h packetizer/hevc_nal.c \
 	packetizer/hxxx_nal.h \
 	packetizer/hxxx_common.c packetizer/hxxx_common.h
+libpacketizer_a52_plugin_la_SOURCES = packetizer/a52.c packetizer/a52.h
 
 libpacketizer_avparser_plugin_la_SOURCES = packetizer/avparser.c \
 	packetizer/avparser.h \
@@ -25,7 +26,6 @@ libpacketizer_avparser_plugin_la_SOURCES = packetizer/avparser.c \
 libpacketizer_avparser_plugin_la_CFLAGS = $(AVCODEC_CFLAGS) $(AVUTIL_CFLAGS) $(AM_CFLAGS)
 libpacketizer_avparser_plugin_la_LIBADD = $(AVCODEC_LIBS) $(AVUTIL_LIBS) $(LIBM)
 
-
 noinst_HEADERS += packetizer/packetizer_helper.h packetizer/startcode_helper.h
 
 packetizer_LTLIBRARIES = \
@@ -39,6 +39,7 @@ packetizer_LTLIBRARIES = \
 	libpacketizer_flac_plugin.la \
 	libpacketizer_hevc_plugin.la \
 	libpacketizer_copy_plugin.la \
+	libpacketizer_a52_plugin.la \
 	$(NULL)
 
 if HAVE_AVCODEC
diff --git a/modules/packetizer/a52.c b/modules/packetizer/a52.c
new file mode 100644
index 0000000..9283f5c
--- /dev/null
+++ b/modules/packetizer/a52.c
@@ -0,0 +1,328 @@
+/*****************************************************************************
+ * a52.c: parse A/52 audio sync info and packetize the stream
+ *****************************************************************************
+ * Copyright (C) 2001-2016 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Stéphane Borel <stef at via.ecp.fr>
+ *          Christophe Massiot <massiot at via.ecp.fr>
+ *          Gildas Bazin <gbazin at videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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_helper.h>
+#include <vlc_modules.h>
+
+#include "a52.h"
+
+#include "packetizer_helper.h"
+
+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_("A/52 audio packetizer") )
+    set_capability( "packetizer", 10 )
+    set_callbacks( Open, Close )
+vlc_module_end ()
+
+struct decoder_sys_t
+{
+    /*
+     * Input properties
+     */
+    int i_state;
+
+    block_bytestream_t bytestream;
+
+    /*
+     * Common properties
+     */
+    date_t  end_date;
+    bool    b_date_set;
+
+    mtime_t i_pts;
+
+    vlc_a52_header_t frame;
+};
+
+static void PacketizeFlush( decoder_t *p_dec )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    date_Set( &p_sys->end_date, 0 );
+    p_sys->i_state = STATE_NOSYNC;
+    block_BytestreamEmpty( &p_sys->bytestream );
+}
+
+static block_t *GetOutBuffer( decoder_t *p_dec )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( !p_sys->b_date_set
+     || p_dec->fmt_out.audio.i_rate != p_sys->frame.i_rate )
+    {
+        msg_Dbg( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
+                 p_sys->frame.i_channels, p_sys->frame.i_rate, p_sys->frame.i_bitrate );
+
+        date_Init( &p_sys->end_date, p_sys->frame.i_rate, 1 );
+        date_Set( &p_sys->end_date, p_sys->i_pts );
+        p_sys->b_date_set = true;
+    }
+
+    p_dec->fmt_out.audio.i_rate     = p_sys->frame.i_rate;
+    p_dec->fmt_out.audio.i_channels = p_sys->frame.i_channels;
+    if( p_dec->fmt_out.audio.i_bytes_per_frame < p_sys->frame.i_size )
+        p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->frame.i_size;
+    p_dec->fmt_out.audio.i_frame_length = p_sys->frame.i_samples;
+
+    p_dec->fmt_out.audio.i_original_channels = p_sys->frame.i_channels_conf;
+    p_dec->fmt_out.audio.i_physical_channels =
+        p_sys->frame.i_channels_conf & AOUT_CHAN_PHYSMASK;
+
+    p_dec->fmt_out.i_bitrate = p_sys->frame.i_bitrate;
+
+    block_t *p_block = block_Alloc( p_sys->frame.i_size );
+    if( p_block == NULL )
+        return NULL;
+
+    p_block->i_nb_samples = p_sys->frame.i_samples;
+    p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
+    p_block->i_length =
+        date_Increment( &p_sys->end_date, p_block->i_nb_samples ) - p_block->i_pts;
+    return p_block;
+}
+
+static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t p_header[VLC_A52_HEADER_SIZE];
+    block_t *p_out_buffer;
+
+    if( !pp_block || !*pp_block ) return NULL;
+
+    if( (*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
+    {
+        if( (*pp_block)->i_flags & BLOCK_FLAG_CORRUPTED )
+        {
+            PacketizeFlush( p_dec );
+            block_Release( *pp_block );
+            *pp_block = NULL;
+            return NULL;
+        }
+        else /* BLOCK_FLAG_DISCONTINUITY */
+            date_Set( &p_sys->end_date, 0 );
+
+    }
+
+    if( !date_Get( &p_sys->end_date ) && (*pp_block)->i_pts <= VLC_TS_INVALID)
+    {
+        /* We've just started the stream, wait for the first PTS. */
+        block_Release( *pp_block );
+        *pp_block = NULL;
+        return NULL;
+    }
+
+    block_BytestreamPush( &p_sys->bytestream, *pp_block );
+
+    while( 1 )
+    {
+        switch( p_sys->i_state )
+        {
+        case STATE_NOSYNC:
+            while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
+                   == VLC_SUCCESS )
+            {
+                if( p_header[0] == 0x0b && p_header[1] == 0x77 )
+                {
+                    p_sys->i_state = STATE_SYNC;
+                    break;
+                }
+                block_SkipByte( &p_sys->bytestream );
+            }
+            if( p_sys->i_state != STATE_SYNC )
+            {
+                block_BytestreamFlush( &p_sys->bytestream );
+
+                /* Need more data */
+                return NULL;
+            }
+
+        case STATE_SYNC:
+            /* New frame, set the Presentation Time Stamp */
+            p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
+            if( p_sys->i_pts > VLC_TS_INVALID &&
+                p_sys->i_pts != date_Get( &p_sys->end_date ) )
+            {
+                date_Set( &p_sys->end_date, p_sys->i_pts );
+            }
+            p_sys->i_state = STATE_HEADER;
+
+        case STATE_HEADER:
+            /* Get A/52 frame header (VLC_A52_HEADER_SIZE bytes) */
+            if( block_PeekBytes( &p_sys->bytestream, p_header,
+                                 VLC_A52_HEADER_SIZE ) != VLC_SUCCESS )
+            {
+                /* Need more data */
+                return NULL;
+            }
+
+            /* Check if frame is valid and get frame info */
+            if( vlc_a52_header_Parse( &p_sys->frame, p_header, VLC_A52_HEADER_SIZE ) )
+            {
+                msg_Dbg( p_dec, "emulated sync word" );
+                block_SkipByte( &p_sys->bytestream );
+                p_sys->i_state = STATE_NOSYNC;
+                break;
+            }
+
+            p_sys->i_state = STATE_NEXT_SYNC;
+
+        case STATE_NEXT_SYNC:
+            /* TODO: If pp_block == NULL, flush the buffer without checking the
+             * next sync word */
+
+            /* Check if next expected frame contains the sync word */
+            if( block_PeekOffsetBytes( &p_sys->bytestream,
+                                       p_sys->frame.i_size, p_header, 2 )
+                != VLC_SUCCESS )
+            {
+                /* Need more data */
+                return NULL;
+            }
+
+            if( p_header[0] == 0 && p_header[1] == 0 )
+            {
+                /* A52 wav files and audio CD's use stuffing */
+                p_sys->i_state = STATE_GET_DATA;
+                break;
+            }
+
+            if( p_header[0] != 0x0b || p_header[1] != 0x77 )
+            {
+                msg_Dbg( p_dec, "emulated sync word "
+                         "(no sync on following frame)" );
+                p_sys->i_state = STATE_NOSYNC;
+                block_SkipByte( &p_sys->bytestream );
+                break;
+            }
+            p_sys->i_state = STATE_SEND_DATA;
+            break;
+
+        case STATE_GET_DATA:
+            /* Make sure we have enough data.
+             * (Not useful if we went through NEXT_SYNC) */
+            if( block_WaitBytes( &p_sys->bytestream,
+                                 p_sys->frame.i_size ) != VLC_SUCCESS )
+            {
+                /* Need more data */
+                return NULL;
+            }
+            p_sys->i_state = STATE_SEND_DATA;
+
+        case STATE_SEND_DATA:
+            if( !(p_out_buffer = GetOutBuffer( p_dec )) )
+            {
+                //p_dec->b_error = true;
+                return NULL;
+            }
+
+            /* Copy the whole frame into the buffer. When we reach this point
+             * we already know we have enough data available. */
+            block_GetBytes( &p_sys->bytestream, p_out_buffer->p_buffer,
+                            __MIN( p_sys->frame.i_size, p_out_buffer->i_buffer ) );
+
+            /* Make sure we don't reuse the same pts twice */
+            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
+                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;
+
+            /* So p_block doesn't get re-added several times */
+            *pp_block = block_BytestreamPop( &p_sys->bytestream );
+
+            p_sys->i_state = STATE_NOSYNC;
+
+            return p_out_buffer;
+        }
+    }
+}
+
+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 );
+
+    free( p_sys );
+}
+
+static int Open( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+
+    switch( p_dec->fmt_in.i_codec )
+    {
+    case VLC_CODEC_A52:
+        break;
+    case VLC_CODEC_EAC3:
+        break;
+    default:
+        return VLC_EGENERIC;
+    }
+
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_dec->p_sys = p_sys =
+          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
+        return VLC_ENOMEM;
+
+    /* Misc init */
+    p_sys->i_state = STATE_NOSYNC;
+    date_Set( &p_sys->end_date, 0 );
+    p_sys->i_pts = VLC_TS_INVALID;
+    p_sys->b_date_set = false;
+
+    block_BytestreamInit( &p_sys->bytestream );
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = AUDIO_ES;
+    p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
+    p_dec->fmt_out.audio = p_dec->fmt_in.audio;
+
+    p_sys->frame.i_rate = p_dec->fmt_out.audio.i_rate;
+    p_sys->frame.i_channels = p_dec->fmt_out.audio.i_channels;
+    p_sys->frame.i_size = p_dec->fmt_out.audio.i_bytes_per_frame;
+    p_sys->frame.i_samples = p_dec->fmt_out.audio.i_frame_length;
+    p_sys->frame.i_channels_conf = p_dec->fmt_out.audio.i_original_channels;
+    p_sys->frame.i_bitrate = p_dec->fmt_out.i_bitrate;
+
+    /* Set callback */
+    p_dec->pf_packetize = PacketizeBlock;
+    p_dec->pf_flush     = PacketizeFlush;
+    return VLC_SUCCESS;
+}
diff --git a/modules/packetizer/a52.h b/modules/packetizer/a52.h
new file mode 100644
index 0000000..3b7315c
--- /dev/null
+++ b/modules/packetizer/a52.h
@@ -0,0 +1,216 @@
+/*****************************************************************************
+ * a52.h
+ *****************************************************************************
+ * Copyright (C) 2001-2009 Laurent Aimar
+ * $Id$
+ *
+ * Authors: Stéphane Borel <stef at via.ecp.fr>
+ *          Christophe Massiot <massiot at via.ecp.fr>
+ *          Gildas Bazin <gbazin at videolan.org>
+ *          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 Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *****************************************************************************/
+
+#ifndef VLC_A52_H_
+#define VLC_A52_H_
+
+#include <vlc_bits.h>
+
+/**
+ * Minimum AC3 header size that vlc_a52_header_Parse needs.
+ */
+#define VLC_A52_HEADER_SIZE (8)
+
+/**
+ * AC3 header information.
+ */
+typedef struct
+{
+    bool b_eac3;
+
+    unsigned int i_channels;
+    unsigned int i_channels_conf;
+    unsigned int i_rate;
+    unsigned int i_bitrate;
+
+    unsigned int i_size;
+    unsigned int i_samples;
+
+} vlc_a52_header_t;
+
+/**
+ * It parse AC3 sync info.
+ *
+ * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
+ * since we don't want to oblige S/PDIF people to use liba52 just to get
+ * their SyncInfo...
+ */
+static inline int vlc_a52_header_ParseAc3( vlc_a52_header_t *p_header,
+                                           const uint8_t *p_buf,
+                                           const uint32_t *p_acmod )
+{
+    static const uint8_t pi_halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
+    static const unsigned int pi_bitrate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
+                                128, 160, 192, 224, 256, 320, 384, 448,
+                                512, 576, 640 };
+    static const uint8_t pi_lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
+                                      0x04, 0x01, 0x04, 0x01 };
+
+    /* */
+    const unsigned i_rate_shift = pi_halfrate[p_buf[5] >> 3];
+
+    /* acmod, dsurmod and lfeon */
+    const unsigned i_acmod = p_buf[6] >> 5;
+    if( (p_buf[6] & 0xf8) == 0x50 )
+        /* Dolby surround = stereo + Dolby */
+        p_header->i_channels_conf = AOUT_CHANS_STEREO | AOUT_CHAN_DOLBYSTEREO;
+    else
+        p_header->i_channels_conf = p_acmod[i_acmod];
+    if( p_buf[6] & pi_lfeon[i_acmod] )
+        p_header->i_channels_conf |= AOUT_CHAN_LFE;
+
+    p_header->i_channels = popcount(p_header->i_channels_conf
+                                                         & AOUT_CHAN_PHYSMASK);
+
+    const unsigned i_frmsizecod = p_buf[4] & 63;
+    if( i_frmsizecod >= 38 )
+        return VLC_EGENERIC;
+    const unsigned i_bitrate_base = pi_bitrate[i_frmsizecod >> 1];
+    p_header->i_bitrate = (i_bitrate_base * 1000) >> i_rate_shift;
+
+    switch( p_buf[4] & 0xc0 )
+    {
+    case 0:
+        p_header->i_rate = 48000 >> i_rate_shift;
+        p_header->i_size = 4 * i_bitrate_base;
+        break;
+    case 0x40:
+        p_header->i_rate = 44100 >> i_rate_shift;
+        p_header->i_size = 2 * (320 * i_bitrate_base / 147 + (i_frmsizecod & 1));
+        break;
+    case 0x80:
+        p_header->i_rate = 32000 >> i_rate_shift;
+        p_header->i_size = 6 * i_bitrate_base;
+        break;
+    default:
+        return VLC_EGENERIC;
+    }
+    p_header->i_samples = 6*256;
+
+    p_header->b_eac3 = false;
+    return VLC_SUCCESS;
+}
+
+/**
+ * It parse E-AC3 sync info
+ */
+static inline int vlc_a52_header_ParseEac3( vlc_a52_header_t *p_header,
+                                            const uint8_t *p_buf,
+                                            const uint32_t *p_acmod )
+{
+    static const unsigned pi_samplerate[3] = { 48000, 44100, 32000 };
+    unsigned i_numblkscod;
+    bs_t s;
+
+
+    bs_init( &s, (void*)p_buf, VLC_A52_HEADER_SIZE );
+    bs_skip( &s, 16 +   /* start code */
+                 2 +    /* stream type */
+                 3 );   /* substream id */
+    const unsigned i_frame_size = bs_read( &s, 11 );
+    if( i_frame_size < 2 )
+        return VLC_EGENERIC;
+    p_header->i_size = 2 * ( i_frame_size + 1 );
+
+    const unsigned i_fscod = bs_read( &s, 2 );
+    if( i_fscod == 0x03 )
+    {
+        const unsigned i_fscod2 = bs_read( &s, 2 );
+        if( i_fscod2 == 0X03 )
+            return VLC_EGENERIC;
+        p_header->i_rate = pi_samplerate[i_fscod2] / 2;
+        i_numblkscod = 6;
+    }
+    else
+    {
+        static const int pi_blocks[4] = { 1, 2, 3, 6 };
+
+        p_header->i_rate = pi_samplerate[i_fscod];
+        i_numblkscod = pi_blocks[bs_read( &s, 2 )];
+    }
+
+    const unsigned i_acmod = bs_read( &s, 3 );
+    const unsigned i_lfeon = bs_read1( &s );
+
+    p_header->i_channels_conf = p_acmod[i_acmod];
+    if( i_lfeon )
+        p_header->i_channels_conf |= AOUT_CHAN_LFE;
+    p_header->i_channels = popcount(p_header->i_channels_conf
+                                                         & AOUT_CHAN_PHYSMASK);
+    p_header->i_bitrate = 8 * p_header->i_size * (p_header->i_rate)
+                                               / (i_numblkscod * 256);
+    p_header->i_samples = i_numblkscod * 256;
+
+    p_header->b_eac3 = true;
+    return VLC_SUCCESS;
+}
+
+/**
+ * It will parse the header AC3 frame and fill vlc_a52_header_t* if
+ * it is valid or return VLC_EGENERIC.
+ *
+ * XXX It will only recognize big endian bitstream ie starting with 0x0b, 0x77
+ */
+static inline int vlc_a52_header_Parse( vlc_a52_header_t *p_header,
+                                        const uint8_t *p_buffer, int i_buffer )
+{
+    static const uint32_t p_acmod[8] = {
+        AOUT_CHANS_2_0 | AOUT_CHAN_DUALMONO,
+        AOUT_CHAN_CENTER,
+        AOUT_CHANS_2_0,
+        AOUT_CHANS_3_0,
+        AOUT_CHANS_FRONT | AOUT_CHAN_REARCENTER, /* 2F1R */
+        AOUT_CHANS_FRONT | AOUT_CHANS_CENTER,    /* 3F1R */
+        AOUT_CHANS_4_0,
+        AOUT_CHANS_5_0,
+    };
+
+    if( i_buffer < VLC_A52_HEADER_SIZE )
+        return VLC_EGENERIC;
+
+    /* Check synword */
+    if( p_buffer[0] != 0x0b || p_buffer[1] != 0x77 )
+        return VLC_EGENERIC;
+
+    /* Check bsid */
+    const int bsid = p_buffer[5] >> 3;
+    if( bsid > 16 )
+        return VLC_EGENERIC;
+
+    if( bsid <= 10 )
+    {
+        if( vlc_a52_header_ParseAc3( p_header, p_buffer, p_acmod ) )
+            return VLC_EGENERIC;
+    }
+    else
+    {
+        if( vlc_a52_header_ParseEac3( p_header, p_buffer, p_acmod ) )
+            return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6d5801c..3abcf38 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -332,7 +332,6 @@ modules/audio_output/volume.h
 modules/audio_output/wasapi.c
 modules/audio_output/waveout.c
 modules/audio_output/windows_audio_common.h
-modules/codec/a52.c
 modules/codec/adpcm.c
 modules/codec/aes3.c
 modules/codec/araw.c
@@ -1001,6 +1000,7 @@ modules/mux/ogg.c
 modules/mux/wav.c
 modules/notify/osx_notifications.m
 modules/notify/notify.c
+modules/packetizer/a52.c
 modules/packetizer/avparser.h
 modules/packetizer/copy.c
 modules/packetizer/dirac.c
-- 
2.8.1




More information about the vlc-devel mailing list