⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg4audio.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * mpeg4audio.c: parse and packetize an MPEG 4 audio stream ***************************************************************************** * Copyright (C) 2001, 2002, 2006 the VideoLAN team * $Id$ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> *          Gildas Bazin <gbazin@netcourrier.com> * * 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_aout.h>#include <vlc_codec.h>#include <vlc_block.h>#include <vlc_sout.h>#include <vlc_codecs.h>#include <vlc_input.h>#include <vlc_bits.h>#include "vlc_block_helper.h"#include <assert.h>/* AAC Config in ES: * * AudioObjectType          5 bits * samplingFrequencyIndex   4 bits * if (samplingFrequencyIndex == 0xF) *  samplingFrequency   24 bits * channelConfiguration     4 bits * GA_SpecificConfig *  FrameLengthFlag         1 bit 1024 or 960 *  DependsOnCoreCoder      1 bit (always 0) *  ExtensionFlag           1 bit (always 0) *//***************************************************************************** * decoder_sys_t : decoder descriptor *****************************************************************************/typedef struct{    int i_object_type;    int i_samplerate;    int i_channel;    int i_sbr;          // 0: no sbr, 1: sbr, -1: unknown    struct    {        int i_object_type;        int i_samplerate;    } extension;    /* GASpecific */    int i_frame_length;   // 1024 or 960} mpeg4_cfg_t;#define LATM_MAX_EXTRA_SIZE 64typedef struct{    int i_program;    int i_layer;    int i_frame_length_type;    int i_frame_length;         // type 1    int i_frame_length_index;   // type 3 4 5 6 7    mpeg4_cfg_t cfg;    /* Raw configuration */    int     i_extra;    uint8_t extra[LATM_MAX_EXTRA_SIZE];} latm_stream_t;#define LATM_MAX_LAYER (8)#define LATM_MAX_PROGRAM (16)typedef struct{    int b_same_time_framing;    int i_sub_frames;    int i_programs;    int pi_layers[LATM_MAX_PROGRAM];    int pi_stream[LATM_MAX_PROGRAM][LATM_MAX_LAYER];    int i_streams;    latm_stream_t stream[LATM_MAX_PROGRAM*LATM_MAX_LAYER];    int i_other_data;    int i_crc;  /* -1 if not set */} latm_mux_t;struct decoder_sys_t{    /*     * Input properties     */    int i_state;    int i_type;    block_bytestream_t bytestream;    /*     * Common properties     */    audio_date_t end_date;    mtime_t i_pts;    int i_frame_size;    unsigned int i_channels;    unsigned int i_rate, i_frame_length, i_header_size;    int i_input_rate;    /* LOAS */    bool b_latm_cfg;    latm_mux_t latm;};enum {    STATE_NOSYNC,    STATE_SYNC,    STATE_HEADER,    STATE_NEXT_SYNC,    STATE_GET_DATA,    STATE_SEND_DATA};enum {    TYPE_NONE,    TYPE_RAW,    TYPE_ADTS,    TYPE_LOAS};static const int pi_sample_rates[16] ={    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,    16000, 12000, 11025, 8000,  7350,  0,     0,     0};#define ADTS_HEADER_SIZE 9#define LOAS_HEADER_SIZE 3/**************************************************************************** * Local prototypes ****************************************************************************/static int  OpenPacketizer( vlc_object_t * );static void ClosePacketizer( vlc_object_t * );static block_t *PacketizeRawBlock    ( decoder_t *, block_t ** );static block_t *PacketizeStreamBlock( decoder_t *, block_t ** );/***************************************************************************** * Module descriptor *****************************************************************************/vlc_module_begin();    set_category( CAT_SOUT );    set_subcategory( SUBCAT_SOUT_PACKETIZER );    set_description( N_("MPEG4 audio packetizer") );    set_capability( "packetizer", 50 );    set_callbacks( OpenPacketizer, ClosePacketizer );vlc_module_end();/***************************************************************************** * OpenPacketizer: probe the packetizer and return score *****************************************************************************/static int OpenPacketizer( 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( 'm', 'p', '4', 'a' ) )    {        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;    aout_DateSet( &p_sys->end_date, 0 );    p_sys->bytestream = block_BytestreamInit();    p_sys->i_input_rate = INPUT_RATE_DEFAULT;    p_sys->b_latm_cfg = false;    /* Set output properties */    p_dec->fmt_out.i_cat = AUDIO_ES;    p_dec->fmt_out.i_codec = VLC_FOURCC('m','p','4','a');    msg_Dbg( p_dec, "running MPEG4 audio packetizer" );    if( p_dec->fmt_in.i_extra > 0 )    {        uint8_t *p_config = (uint8_t*)p_dec->fmt_in.p_extra;        int     i_index;        i_index = ( ( p_config[0] << 1 ) | ( p_config[1] >> 7 ) ) & 0x0f;        if( i_index != 0x0f )        {            p_dec->fmt_out.audio.i_rate = pi_sample_rates[i_index];            p_dec->fmt_out.audio.i_frame_length =                (( p_config[1] >> 2 ) & 0x01) ? 960 : 1024;        }        else        {            p_dec->fmt_out.audio.i_rate = ( ( p_config[1] & 0x7f ) << 17 ) |                ( p_config[2] << 9 ) | ( p_config[3] << 1 ) |                ( p_config[4] >> 7 );            p_dec->fmt_out.audio.i_frame_length =                (( p_config[4] >> 2 ) & 0x01) ? 960 : 1024;        }        p_dec->fmt_out.audio.i_channels =            (p_config[i_index == 0x0f ? 4 : 1] >> 3) & 0x0f;        msg_Dbg( p_dec, "AAC %dHz %d samples/frame",                 p_dec->fmt_out.audio.i_rate,                 p_dec->fmt_out.audio.i_frame_length );        aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );        p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;        p_dec->fmt_out.p_extra = malloc( p_dec->fmt_in.i_extra );        if( !p_dec->fmt_out.p_extra )        {            p_dec->fmt_out.i_extra = 0;            return VLC_ENOMEM;        }        memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra,                p_dec->fmt_in.i_extra );        /* Set callback */        p_dec->pf_packetize = PacketizeRawBlock;        p_sys->i_type = TYPE_RAW;    }    else    {        msg_Dbg( p_dec, "no decoder specific info, must be an ADTS or LOAS stream" );        aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );        /* We will try to create a AAC Config from adts/loas */        p_dec->fmt_out.i_extra = 0;        p_dec->fmt_out.p_extra = NULL;        /* Set callback */        p_dec->pf_packetize = PacketizeStreamBlock;        p_sys->i_type = TYPE_NONE;    }    return VLC_SUCCESS;}/**************************************************************************** * PacketizeRawBlock: the whole thing **************************************************************************** * This function must be fed with complete frames. ****************************************************************************/static block_t *PacketizeRawBlock( decoder_t *p_dec, block_t **pp_block ){    decoder_sys_t *p_sys = p_dec->p_sys;    block_t *p_block;    if( !pp_block || !*pp_block ) return NULL;    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )    {        //aout_DateSet( &p_sys->end_date, 0 );        block_Release( *pp_block );        return NULL;    }    p_block = *pp_block;    *pp_block = NULL; /* Don't reuse this block */    if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )    {        /* We've just started the stream, wait for the first PTS. */        block_Release( p_block );        return NULL;    }    else if( p_block->i_pts != 0 &&             p_block->i_pts != aout_DateGet( &p_sys->end_date ) )    {        aout_DateSet( &p_sys->end_date, p_block->i_pts );    }    p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );    p_block->i_length = aout_DateIncrement( &p_sys->end_date,        p_dec->fmt_out.audio.i_frame_length * p_sys->i_input_rate / INPUT_RATE_DEFAULT ) - p_block->i_pts;    return p_block;}/**************************************************************************** * ADTS helpers ****************************************************************************/static int ADTSSyncInfo( decoder_t * p_dec, const uint8_t * p_buf,                         unsigned int * pi_channels,                         unsigned int * pi_sample_rate,                         unsigned int * pi_frame_length,                         unsigned int * pi_header_size ){    int i_profile, i_sample_rate_idx, i_frame_size;    bool b_crc;    /* Fixed header between frames */    //int i_id = ( (p_buf[1] >> 3) & 0x01) ? 2 : 4; /* MPEG-2 or 4 */    b_crc = !(p_buf[1] & 0x01);    i_profile = p_buf[2] >> 6;    i_sample_rate_idx = (p_buf[2] >> 2) & 0x0f;    *pi_sample_rate = pi_sample_rates[i_sample_rate_idx];    //private_bit = (p_buf[2] >> 1) & 0x01;    *pi_channels = ((p_buf[2] & 0x01) << 2) | ((p_buf[3] >> 6) & 0x03);    //original_copy = (p_buf[3] >> 5) & 0x01;    //home = (p_buf[3] >> 4) & 0x01;    /* Variable header */    //copyright_id_bit = (p_buf[3] >> 3) & 0x01;    //copyright_id_start = (p_buf[3] >> 2) & 0x01;    i_frame_size = ((p_buf[3] & 0x03) << 11) | (p_buf[4] << 3) |                   ((p_buf[5] >> 5) /*& 0x7*/);    //uint16_t buffer_fullness = ((p_buf[5] & 0x1f) << 6) | (p_buf[6] >> 2);    unsigned short i_raw_blocks_in_frame = p_buf[6] & 0x03;    if( !*pi_sample_rate || !*pi_channels || !i_frame_size )    {        msg_Warn( p_dec, "Invalid ADTS header" );        return 0;    }    *pi_frame_length = 1024;    if( i_raw_blocks_in_frame == 0 )    {        if( b_crc )        {            msg_Warn( p_dec, "ADTS CRC not supported" );            //uint16_t crc = (p_buf[7] << 8) | p_buf[8];        }    }    else    {        msg_Err( p_dec, "Multiple blocks per frame in ADTS not supported" );        return 0;#if 0        int i;        const uint8_t *p_pos = p_buf + 7;        uint16_t crc_block;        uint16_t i_block_pos[3];        if( b_crc )        {            for( i = 0 ; i < i_raw_blocks_in_frame ; i++ )            {   /* the 1st block's position is known ... */                i_block_pos[i] = (*p_pos << 8) | *(p_pos+1);                p_pos += 2;            }            crc_block = (*p_pos << 8) | *(p_pos+1);            p_pos += 2;        }        for( i = 0 ; i <= i_raw_blocks_in_frame ; i++ )        {            //read 1 block            if( b_crc )            {                msg_Err( p_dec, "ADTS CRC not supported" );                //uint16_t crc = (*p_pos << 8) | *(p_pos+1);                //p_pos += 2;            }        }#endif    }    /* Build the decoder specific info header */    if( !p_dec->fmt_out.i_extra )    {        p_dec->fmt_out.p_extra = malloc( 2 );        if( !p_dec->fmt_out.p_extra )        {            p_dec->fmt_out.i_extra = 0;            return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -