+++ /dev/null
-/*****************************************************************************
- * demux.c : Raw aac Stream input module for vlc
- *****************************************************************************
- * Copyright (C) 2001 VideoLAN
- * $Id: demux.c,v 1.10 2003/05/14 21:29:42 fenrir Exp $
- *
- * Authors: Laurent Aimar <fenrir@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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <stdlib.h> /* malloc(), free() */
-#include <string.h>
-
-#include <vlc/vlc.h>
-#include <vlc/input.h>
-
-#include <sys/types.h>
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-static int Activate ( vlc_object_t * );
-static int Demux ( input_thread_t * );
-static void Deactivate ( vlc_object_t * );
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-vlc_module_begin();
- set_description( _("AAC stream demuxer" ) );
- set_capability( "demux", 10 );
- set_callbacks( Activate, NULL );
- add_shortcut( "aac" );
-vlc_module_end();
-
-/*****************************************************************************
- * Definitions of structures and functions used by this plugins
- *****************************************************************************/
-#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
-/* XXX set this to 0 to avoid problem with PS XXX */
-/* but with some file or web radio will failed to detect */
-/* it's you to choose */
-#define AAC_MAXTESTPOS 0
-
-static int i_aac_samplerate[16] =
-{
- 96000, 88200, 64000, 48000, 44100, 32000,
- 24000, 22050, 16000, 12000, 11025, 8000,
- 7350, 0, 0, 0
-};
-
-typedef struct adts_header_s
-{
- int i_id;
- int i_framelength;
- int i_layer;
- int i_protection_absent;
- int i_profile;
- int i_samplerate_index;
- int i_private_bit;
- int i_channel_configuration;
- int i_original;
- int i_home;
- int i_emphasis;
- int i_copyright_identification_bit;
- int i_copyright_identification_start;
- int i_aac_frame_length;
- int i_adts_buffer_fullness;
- int i_no_raw_data_blocks_in_frame;
- int i_crc_check;
-
-} adts_header_t;
-
-/* Not yet used */
-typedef struct adif_header_s
-{
- int b_copyright_id_present;
- uint8_t i_copyright_id[10];
-
- int b_original_copy;
-
- int i_home;
- int i_bitstream_type;
- int i_bitrate;
- int i_num_program_config_elements;
- int adif_buffer_fullness;
-
-// program_config_element
-
-
-} adif_header_t;
-
-struct demux_sys_t
-{
- mtime_t i_pts;
-
- es_descriptor_t *p_es;
-
- int b_adif_header;
- adif_header_t adif_header;
-
- int b_adts_header;
- adts_header_t adts_header;
-
- /* extracted information */
- int i_samplerate_index;
- int i_object_type;
- int i_samplerate;
- int i_channels;
- int i_framelength;
- int i_aac_frame_length;
-};
-
-/****************************************************************************
- * bit_* : function to get a bitstream from a memory buffer
- ****************************************************************************
- *
- ****************************************************************************/
-typedef struct bit_s
-{
- uint8_t *p_buffer;
- int i_buffer;
- int i_mask;
-} bit_t;
-
-static void bit_init( bit_t *p_bit,
- uint8_t *p_buffer,
- int i_buffer )
-{
- p_bit->p_buffer = p_buffer;
- p_bit->i_buffer = i_buffer;
- p_bit->i_mask = 0x80;
-}
-
-static uint32_t bit_get( bit_t *p_bit )
-{
- uint32_t i_bit;
- if( p_bit->i_buffer <= 0 )
- {
- return( 0 );
- }
- i_bit = ( p_bit->p_buffer[0]&p_bit->i_mask ) ? 1 : 0;
-
- p_bit->i_mask >>= 1;
- if( !p_bit->i_mask )
- {
- p_bit->p_buffer++;
- p_bit->i_buffer--;
- p_bit->i_mask = 0x80;
- }
- return( i_bit );
-}
-
-static uint32_t bit_gets( bit_t *p_bit, int i_count )
-{
- uint32_t i_bits;
- i_bits = 0;
- for( ; i_count > 0; i_count-- )
- {
- i_bits = ( i_bits << 1 )|bit_get( p_bit );
- }
- return( i_bits );
-}
-
-/*****************************************************************************
- * Function to manipulate stream easily
- *****************************************************************************
- *
- * SkipBytes : skip bytes :) not yet uoptimised ( read bytes to be skipped )
- *
- * ReadPes : read data and make a PES
- *
- *****************************************************************************/
-static int SkipBytes( input_thread_t *p_input, int i_size )
-{
- data_packet_t *p_data;
- int i_read;
-
- while( i_size > 0 )
- {
- i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size, 1024 ) );
- if( i_read <= 0 )
- {
- return( 0 );
- }
- input_DeletePacket( p_input->p_method_data, p_data );
- i_size -= i_read;
- }
- return( 1 );
-}
-
-static int ReadPES( input_thread_t *p_input,
- pes_packet_t **pp_pes,
- int i_size )
-{
- pes_packet_t *p_pes;
-
- *pp_pes = NULL;
-
- if( !(p_pes = input_NewPES( p_input->p_method_data )) )
- {
- msg_Err( p_input, "cannot allocate new PES" );
- return( 0 );
- }
-
- while( i_size > 0 )
- {
- data_packet_t *p_data;
- int i_read;
-
- if( (i_read = input_SplitBuffer( p_input,
- &p_data,
- __MIN( i_size, 1024 ) ) ) <= 0 )
- {
- input_DeletePES( p_input->p_method_data, p_pes );
- return( 0 );
- }
- if( !p_pes->p_first )
- {
- p_pes->p_first = p_data;
- p_pes->i_nb_data = 1;
- p_pes->i_pes_size = i_read;
- }
- else
- {
- p_pes->p_last->p_next = p_data;
- p_pes->i_nb_data++;
- p_pes->i_pes_size += i_read;
- }
- p_pes->p_last = p_data;
- i_size -= i_read;
- }
- *pp_pes = p_pes;
- return( 1 );
-}
-
-/*****************************************************************************
- * GetADIF: find and load adif header if present
- *****************************************************************************/
-static int GetADIF( input_thread_t *p_input,
- adif_header_t *p_adif )
-{
- uint8_t *p_peek;
- int i_size;
-
- if( ( i_size = input_Peek( p_input, &p_peek, 60 ) ) < 60 )
- {
- /* it's false, min size is 11 byte but easier ;) */
- return( 0 );
- }
- if( ( p_peek[0] != 'A' )||( p_peek[1] != 'D' )||
- ( p_peek[2] != 'I' )||( p_peek[3] != 'F' ) )
- {
- return( 0 );
- }
-
- /* we now that we have an adif header */
-
-// return( 1 );
- return( 0 ); /* need some work */
-}
-
-/*****************************************************************************
- * GetADTS: find and load adts header
- *****************************************************************************/
-#define ADTS_HEADERSIZE 10 /* 8+2 for crc */
-static int GetADTS( input_thread_t *p_input,
- adts_header_t *p_adts,
- int i_max_pos,
- int *pi_skip )
-{
- uint8_t *p_peek;
- int i_size;
- bit_t bit;
-
- if( ( i_size = input_Peek( p_input, &p_peek, i_max_pos + ADTS_HEADERSIZE ) )
- < ADTS_HEADERSIZE )
- {
- return( 0 );
- }
- *pi_skip = 0;
- for( ; ; )
- {
- if( i_size < ADTS_HEADERSIZE )
- {
- return( 0 );
- }
- if( ( p_peek[0] != 0xff )||
- ( ( p_peek[1]&0xf6 ) != 0xf0 ) ) /* Layer == 0 */
- {
- p_peek++;
- i_size--;
- *pi_skip += 1;
- continue;
- }
- /* we have find an adts header, load it */
- break;
- }
-
- bit_init( &bit, p_peek, i_size );
- bit_gets( &bit, 12 ); /* synchro bits */
-
- p_adts->i_id = bit_get( &bit );
- p_adts->i_layer = bit_gets( &bit, 2);
- p_adts->i_protection_absent = bit_get( &bit );
- p_adts->i_profile = bit_gets( &bit, 2 );
- p_adts->i_samplerate_index = bit_gets( &bit, 4);
- p_adts->i_private_bit = bit_get( &bit );
- p_adts->i_channel_configuration = bit_gets( &bit, 3);
- p_adts->i_original = bit_get( &bit );
- p_adts->i_home = bit_get( &bit );
- if( p_adts->i_id == 0 )
- {
- p_adts->i_emphasis = bit_gets( &bit, 2);
- }
-
- p_adts->i_copyright_identification_bit = bit_get( &bit );
- p_adts->i_copyright_identification_start = bit_get( &bit );
- p_adts->i_aac_frame_length = bit_gets( &bit, 13 );
- p_adts->i_adts_buffer_fullness = bit_gets( &bit, 11 );
- p_adts->i_no_raw_data_blocks_in_frame = bit_gets( &bit, 2 );
-
- if( p_adts->i_protection_absent == 0 )
- {
- p_adts->i_crc_check = bit_gets( &bit, 16 );
- }
- return( 1 );
-}
-
-static void ExtractConfiguration( demux_sys_t *p_aac )
-{
- if( p_aac->b_adif_header )
- {
-
- }
- if( p_aac->b_adts_header )
- {
- p_aac->i_samplerate_index = p_aac->adts_header.i_samplerate_index;
- p_aac->i_object_type = p_aac->adts_header.i_profile;
- p_aac->i_samplerate = i_aac_samplerate[p_aac->i_samplerate_index];
- p_aac->i_channels = p_aac->adts_header.i_channel_configuration;
- if( p_aac->i_channels > 6 )
- {
- /* I'm not sure of that, got from faad */
- p_aac->i_channels = 2;
- }
- p_aac->i_aac_frame_length = p_aac->adts_header.i_aac_frame_length;
- p_aac->i_framelength = 1024;
- }
- /* FIXME FIXME for LD, but LD = ?
- if( p_aac->i_object_type == LD )
- {
- p_aac->i_framelength /= 2;
- }
- */
-}
-
-#if 0
-/****************************************************************************
- * CheckPS : check if this stream could be some ps,
- * yes it's ugly ... but another idea ?
- * XXX it seems that aac stream always match ...
- ****************************************************************************/
-static int CheckPS( input_thread_t *p_input )
-{
- uint8_t *p_peek;
- int i_size = input_Peek( p_input, &p_peek, 8196 );
-
- while( i_size > 4 )
- {
- if( ( p_peek[0] == 0 ) && ( p_peek[1] == 0 )&&
- ( p_peek[2] == 1 ) && ( p_peek[3] >= 0xb9 ) )
- {
- return( 1 ); /* Perhaps some ps stream */
- }
- p_peek++;
- i_size--;
- }
- return( 0 );
-}
-#endif
-
-/*****************************************************************************
- * Activate: initializes AAC demux structures
- *****************************************************************************/
-static int Activate( vlc_object_t * p_this )
-{
- input_thread_t * p_input = (input_thread_t *)p_this;
- demux_sys_t * p_aac;
- input_info_category_t * p_category;
- module_t * p_id3;
-
- int i_skip;
- int b_forced = VLC_FALSE;
-
- if( p_input->psz_demux && !strncmp( p_input->psz_demux, "aac", 3 ) )
- {
- b_forced = VLC_TRUE;
- }
- else if( p_input->psz_name )
- {
- int i_len = strlen( p_input->psz_name );
-
- if( i_len > 4 && !strcasecmp( &p_input->psz_name[i_len - 4], ".aac" ) )
- {
- b_forced = VLC_TRUE;
- }
- }
-
- if( !b_forced )
- {
- return -1;
- }
-
- /* Set the demux function */
- p_input->pf_demux = Demux;
-
- /* Initialize access plug-in structures. */
- if( p_input->i_mtu == 0 )
- {
- /* Improve speed. */
- p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
- }
-
- /* skip possible id3 header */
- p_id3 = module_Need( p_input, "id3", NULL );
- if ( p_id3 ) {
- module_Unneed( p_input, p_id3 );
- }
-
- /* allocate p_aac */
- if( !( p_aac = malloc( sizeof( demux_sys_t ) ) ) )
- {
- msg_Err( p_input, "out of memory" );
- return( -1 );
- }
- memset( p_aac, 0, sizeof( demux_sys_t ) );
-
- /* Now check for adif/adts header */
- i_skip = 0;
- if( GetADIF( p_input, &p_aac->adif_header ) )
- {
- p_aac->b_adif_header = 1;
- msg_Err( p_input,
- "found ADIF header (unsupported)" );
- free( p_aac );
- return( -1 );
- }
- else
- if( GetADTS( p_input,
- &p_aac->adts_header,
- b_forced ? 8000 : 0,
- &i_skip ) )
- {
- p_aac->b_adts_header = 1;
- msg_Info( p_input,
- "found ADTS header" );
- }
- else
- {
- msg_Warn( p_input,
- "AAC module discarded (no header found)" );
- free( p_aac );
- return( -1 );
- }
- ExtractConfiguration( p_aac );
-
- vlc_mutex_lock( &p_input->stream.stream_lock );
- if( input_InitStream( p_input, 0 ) == -1)
- {
- vlc_mutex_unlock( &p_input->stream.stream_lock );
- msg_Err( p_input, "cannot init stream" );
- return( -1 );
- }
- if( input_AddProgram( p_input, 0, 0) == NULL )
- {
- vlc_mutex_unlock( &p_input->stream.stream_lock );
- msg_Err( p_input, "cannot add program" );
- return( -1 );
- }
- p_input->stream.pp_programs[0]->b_is_ok = 0;
- p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
-
- /* create our ES */
- p_aac->p_es = input_AddES( p_input, p_input->stream.p_selected_program,
- 1 /* id */, AUDIO_ES, NULL, 0 );
- if( !p_aac->p_es )
- {
- vlc_mutex_unlock( &p_input->stream.stream_lock );
- msg_Err( p_input, "out of memory" );
- return( -1 );
- }
-
- p_aac->p_es->i_stream_id = 1;
- p_aac->p_es->i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'a' );
- input_SelectES( p_input, p_aac->p_es );
-
- p_input->stream.p_selected_program->b_is_ok = 1;
- vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-
-
- vlc_mutex_lock( &p_input->stream.stream_lock );
- if( p_aac->b_adif_header )
- {
- p_input->stream.i_mux_rate = 0 / 50;
- }
- if( p_aac->b_adts_header )
- {
- p_input->stream.i_mux_rate = 0 / 50;
- }
- vlc_mutex_unlock( &p_input->stream.stream_lock );
-#if 0
- /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
- /* if i don't do that, it don't work correctly but why ??? */
- if( p_input->stream.b_seekable )
- {
- p_input->pf_seek( p_input, 0 );
- input_AccessReinit( p_input );
- }
- /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
-#endif
-
- /* all is ok :)) */
- if( p_aac->b_adif_header )
- {
- }
-
- if( p_aac->b_adts_header )
- {
- msg_Dbg( p_input,
- "audio AAC MPEG-%d layer-%d %d channels %dHz",
- p_aac->adts_header.i_id == 1 ? 2 : 4,
- 4 - p_aac->adts_header.i_layer, /* it's always 4 in fact */
- p_aac->i_channels,
- p_aac->i_samplerate );
-
- vlc_mutex_lock( &p_input->stream.stream_lock );
- p_category = input_InfoCategory( p_input, _("Aac") );
-
- input_AddInfo( p_category, _("Input Type"), "MPEG-%d AAC",
- p_aac->adts_header.i_id == 1 ? 2 : 4 );
-
- input_AddInfo( p_category, _("Layer"), "%d",
- 4 - p_aac->adts_header.i_layer );
- input_AddInfo( p_category, _("Channels"), "%d",
- p_aac->i_channels );
- input_AddInfo( p_category, _("Sample Rate"), "%dHz",
- p_aac->i_samplerate );
-
- vlc_mutex_unlock( &p_input->stream.stream_lock );
- }
-
- p_input->p_demux_data = p_aac;
-
-
- return( 0 );
-}
-
-/*****************************************************************************
- * Demux: reads and demuxes data packets
- *****************************************************************************
- * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
- *****************************************************************************/
-static int Demux( input_thread_t * p_input )
-{
- int i_skip;
- int i_found;
-
- pes_packet_t *p_pes;
- demux_sys_t *p_aac = p_input->p_demux_data;
-
- /* Get a frame */
- if( p_aac->b_adif_header )
- {
- i_skip = 0;
- return( -1 ); /* FIXME */
- }
- else
- if( p_aac->b_adts_header )
- {
- i_found = GetADTS( p_input,
- &p_aac->adts_header,
- 8000,
- &i_skip );
- }
- else
- {
- return( -1 );
- }
- ExtractConfiguration( p_aac );
-
- /* skip garbage bytes */
- if( i_skip > 0 )
- {
- msg_Dbg( p_input,
- "skipping %d bytes",
- i_skip );
- SkipBytes( p_input, i_skip );
- }
-
- if( !i_found )
- {
- msg_Info( p_input, "can't find next frame" );
- return( 0 );
- }
-
- input_ClockManageRef( p_input,
- p_input->stream.p_selected_program,
- p_aac->i_pts );
-
- if( !ReadPES( p_input, &p_pes, p_aac->i_aac_frame_length ) )
- {
- msg_Warn( p_input,
- "cannot read data" );
- return( -1 );
- }
- p_pes->i_dts =
- p_pes->i_pts = input_ClockGetTS( p_input,
- p_input->stream.p_selected_program,
- p_aac->i_pts );
-
- if( !p_aac->p_es->p_decoder_fifo )
- {
- msg_Err( p_input, "no audio decoder" );
- input_DeletePES( p_input->p_method_data, p_pes );
- return( -1 ); /* perhaps not, it's my choice */
- }
- else
- {
- input_DecodePES( p_aac->p_es->p_decoder_fifo, p_pes );
- }
-
- /* Update date information */
- p_aac->i_pts += (mtime_t)90000 *
- (mtime_t)p_aac->i_framelength /
- (mtime_t)p_aac->i_samplerate;
-
- return( 1 );
-}
-
-static void Deactivate( vlc_object_t * p_this )
-{
- input_thread_t *p_input = (input_thread_t*)p_this;
-// demux_sys_t *p_aac = p_input->p_demux_data;
-
- FREE( p_input->p_demux_data );
-}
-