📄 mpeg4audio.c
字号:
/***************************************************************************** * mpeg4audio.c: parse and packetize an MPEG 4 audio stream ***************************************************************************** * Copyright (C) 2001, 2002 VideoLAN * $Id: mpeg4audio.c 10101 2005-03-02 16:47:31Z robux4 $ * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h> /* malloc(), free() */#include <string.h> /* strdup() */#include <vlc/vlc.h>#include <vlc/aout.h>#include <vlc/decoder.h>#include <vlc/input.h>#include <vlc/sout.h>#include "codecs.h"#include "vlc_block_helper.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 *****************************************************************************/struct decoder_sys_t{ /* * Input properties */ int i_state; block_bytestream_t bytestream; /* * Common properties */ audio_date_t end_date; mtime_t i_pts; int i_frame_size, i_raw_blocks; unsigned int i_channels; unsigned int i_rate, i_frame_length, i_header_size;};enum { STATE_NOSYNC, STATE_SYNC, STATE_HEADER, STATE_NEXT_SYNC, STATE_GET_DATA, STATE_SEND_DATA};static int i_sample_rates[] ={ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0};#define ADTS_HEADER_SIZE 9/**************************************************************************** * Local prototypes ****************************************************************************/static int OpenPacketizer( vlc_object_t * );static void ClosePacketizer( vlc_object_t * );static block_t *PacketizeBlock ( decoder_t *, block_t ** );static block_t *ADTSPacketizeBlock( decoder_t *, block_t ** );static uint8_t *GetOutBuffer ( decoder_t *, void ** );static int ADTSSyncInfo( decoder_t *, const byte_t * p_buf, unsigned int * pi_channels, unsigned int * pi_sample_rate, unsigned int * pi_frame_length, unsigned int * pi_header_size, unsigned int * pi_raw_blocks );/***************************************************************************** * Module descriptor *****************************************************************************/vlc_module_begin(); set_category( CAT_SOUT ); set_subcategory( SUBCAT_SOUT_PACKETIZER ); set_description( _("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 ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } /* Misc init */ p_sys->i_state = STATE_NOSYNC; aout_DateSet( &p_sys->end_date, 0 ); p_sys->bytestream = block_BytestreamInit( p_dec ); /* Set output properties */ p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_codec = VLC_FOURCC('m','p','4','a'); /* Set callback */ p_dec->pf_packetize = PacketizeBlock; msg_Info( 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 = i_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; } 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.audio.i_channels = p_dec->fmt_in.audio.i_channels; 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 ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); } else { msg_Dbg( p_dec, "no decoder specific info, must be an ADTS stream" ); /* We will try to create a AAC Config from adts */ p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.p_extra = NULL; p_dec->pf_packetize = ADTSPacketizeBlock; } return VLC_SUCCESS;}/**************************************************************************** * PacketizeBlock: the whole thing **************************************************************************** * This function must be fed with complete frames. ****************************************************************************/static block_t *PacketizeBlock( 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; 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_block->i_pts; return p_block;}/**************************************************************************** * DTSPacketizeBlock: the whole thing ****************************************************************************/static block_t *ADTSPacketizeBlock( decoder_t *p_dec, block_t **pp_block ){ decoder_sys_t *p_sys = p_dec->p_sys; uint8_t p_header[ADTS_HEADER_SIZE]; void *p_out_buffer; uint8_t *p_buf; if( !pp_block || !*pp_block ) return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -