📄 mpegdec.c
字号:
// #18 Beginint MPEGDEC_scale( MPEGDEC_STREAM *mpds, INT32 scale_percent ) {/*-------------------------------------------------------------------------- Set the output scale for the current stream Inputs: mpds = mpeg audio stream ptr returned by MPEGDEC_open scale_percent = scale factor in % to apply to the decoded output 100 is the nominal value Return 0 if Ok, MPEGDEC_ERR_BADVALUE if invalid scale*/ MPA_STREAM *mps; mps = (MPA_STREAM *)mpds->handle; if( MPEGSUB_scale( mps->mpegsub, scale_percent ) ) return MPEGDEC_ERR_BADVALUE; return MPEGDEC_ERR_NONE;}// #18 EndINT32 MPEGDEC_decode_frame( MPEGDEC_STREAM *mpds, INT16 *pcm[ MPEGDEC_MAX_CHANNELS ] )/*-------------------------------------------------------------------------- Decode the current MPEG Audio frame Input: mpds = mpeg audio stream ptr returned by MPEGDEC_open Output: pcm[] = 16-bit samples pcm[ 0 ] is mono or left voice or channel 1 pcm[ 1 ] is right or channel 2 Return the number of samples Note: pcm[]'s be at least arrays of MPEGDEC_PCM_SIZE number of samples can be 0 if current frame is skipped, in case of error in crc or not enough data for decoding (layer III) number of samples = 0 does not indicate end of stream !*/{ MPA_STREAM *mps; INT32 count; int err; mps = (MPA_STREAM *)mpds->handle; mps->pcm[ 0 ] = pcm[ 0 ]; mps->pcm[ 1 ] = pcm[ 1 ]; if( mps->need_sync ) { // #10 err = synchronize( mps ); if( err ) return err; mps->need_sync = FALSE; } else { err = MPEGDEC_read_header( mps, FALSE ); // #5 FALSE: don't fail if MPEG Audio sync not at first if( err ) return err; }#ifdef MPEGAUD_DEMO MPEGAUD_CHECK_DEMO_FRAME( frame_count ); frame_count++;#endif//fill_info( mpds ); switch( mps->header.layer ) { case 1: count = MPEG1_decode_frame( mps ); break; case 2: count = MPEG2_decode_frame( mps ); break; case 3: count = MPEG3_decode_frame( mps ); break; default: count = 0; } mps->frame++; return count;} /* MPEGDEC_decode_frame */static int decoder_reset( MPEGDEC_STREAM *mpds )/*-------------------------------------------------------------------------- Reset the decoder Inputs: mpds = mpeg audio stream ptr returned by MPEGDEC_open*/{ int err; MPA_STREAM *mps; if( !mpds ) return MPEGDEC_ERR_EOF; mps = (MPA_STREAM *)mpds->handle; // Reset all layer's decoders err = MPEG1_reset( mps ); if( err ) return err; err = MPEG2_reset( mps ); if( err ) return err; err = MPEG3_reset( mps ); if( err ) return err; // Reset subband buffers & offsets err = MPEGSUB_reset( mps->mpegsub ); if( err ) return err; // #8 err = MPEGIMDCT_reset( mps->mpegimdct ); // #8 return err;} /* decoder_reset */int MPEGDEC_seek( MPEGDEC_STREAM *mpds, UINT32 ms_time_position )/*-------------------------------------------------------------------------- Seek into an MPEG Audio stream Inputs: mpds = mpeg audio stream ptr returned by MPEGDEC_open ms_time_position = absolute time position in ms*/{ int err = -1; MPA_STREAM *mps; if( !mpds ) return MPEGDEC_ERR_EOF; mps = (MPA_STREAM *)mpds->handle; if( mps ) { BITSTREAM *bs = mps->bitstream; REAL exact_seek; REAL slots; INT32 seek_pos; INT32 frame_bytes; INT32 frame; // #11 exact_seek = ((REAL)mps->bitrate * (REAL)ms_time_position) * 0.125; // Calculate nearest # of frames if( mps->header.layer == 1 ) frame_bytes = 48000; // 384/8*1000 else if( (mps->header.layer == 3) && (mps->header.ID == MPA_ID_2) ) frame_bytes = 72000; else frame_bytes = 144000; slots = (REAL)(frame_bytes * mps->bitrate) / (REAL)mps->sfreq; frame = (INT32)( exact_seek / slots ); // Calcultate seek pos in multiple of frames seek_pos = (INT32)((REAL)frame * slots); // Here sub 1 to be sure to get header seek_pos--; if( seek_pos < 0 ) seek_pos = 0; seek_pos += mps->bitstream_start_pos; // #17 err = BSTR_seek( bs, seek_pos ); if( !err ) { mps->frame = frame; // #11 decoder_reset( mpds ); mps->need_sync = TRUE; // #10 } } return err;} /* MPEGDEC_seek */int MPEGDEC_time( MPEGDEC_STREAM *mpds, UINT32 *ms_time_position )/*-------------------------------------------------------------------------- Get the current time position of an MPEG Audio stream Input: mpds = mpeg audio stream ptr returned by MPEGDEC_open Output: ms_time_position = absolute time position in ms Return 0 if Ok*/{ int err = -1; MPA_STREAM *mps; if( !mpds ) return MPEGDEC_ERR_EOF; mps = (MPA_STREAM *)mpds->handle; if( mps ) { INT32 frame_bits; if( mps->header.layer == 1 ) frame_bits = 384000; // 384*1000 else if( (mps->header.layer == 3) && (mps->header.ID == MPA_ID_2) ) frame_bits = 576000; else frame_bits = 1152000; *ms_time_position = (UINT32)(((REAL)mps->frame * (REAL)frame_bits ) / (REAL)mps->sfreq); err = 0; } return err;} /* MPEGDEC_time */void MPEGDEC_close( MPEGDEC_STREAM *mpds )/*-------------------------------------------------------------------------- Close an MPEG Audio stream Input: mpds = mpeg audio stream ptr returned by MPEGDEC_open*/{ MPA_STREAM *mps; if( !mpds ) return; mps = (MPA_STREAM *)mpds->handle; if( mps ) { if( mps->mpegimdct ) MPEGIMDCT_close( mps->mpegimdct ); // #8 if( mps->mpegsub ) MPEGSUB_close( mps->mpegsub ); if( mps->huffman ) HUFF_close( mps->huffman ); if( mps->bitstream ) BSTR_close( mps->bitstream ); free( mps ); } free( mpds );} /* MPEGDEC_close */MPEGDEC_STREAM *MPEGDEC_open( char *filename, MPEGDEC_CTRL *ctrl )/*-------------------------------------------------------------------------- Open an MPEG Audio stream Inputs: filename = stream filename to decode ctrl = decoding controls Return the mpeg audio stream ptr or NULL if failed to open stream*/{ MPEGDEC_STREAM *mpds; MPA_STREAM *mps; INT16 freq_div; INT16 quality; INT32 freq_max; INT32 buffer_size; // #6 MPEGDEC_LAYER *dec_lay; // #13 MPEGDEC_OUTPUT *dec_out; // #13 mpds = (MPEGDEC_STREAM *)malloc( sizeof( MPEGDEC_STREAM ) ); if( !mpds ) return NULL; memset( mpds, 0, sizeof( MPEGDEC_STREAM ) ); mps = (MPA_STREAM *)malloc( sizeof( MPA_STREAM ) ); if( !mps ) { MPEGDEC_close( mpds ); return NULL; } memset( mps, 0, sizeof( MPA_STREAM ) ); mpds->handle = mps; // #7 Begin buffer_size = ctrl->stream_buffer_size & (INT32)(~3); // Multiple of 4 bytes if( buffer_size <= 0 ) buffer_size = MPEGDEC_BITSTREAM_BUFFER_SIZE; // #7 End mps->bitstream = BSTR_open( (BITSTREAM_ACCESS *)ctrl->bs_access, filename, buffer_size /* #7 */ ); if( !mps->bitstream ) { MPEGDEC_close( mpds ); return NULL; } mps->stream_size = mps->bitstream->bitstream_size; mps->huffman = HUFF_open(); if( !mps->huffman ) { MPEGDEC_close( mpds ); return NULL; } mps->current_table = -1;// #17 Begin#if 1 if( synchronize( mps ) ) { (void)MPEGDEC_close( mpds ); return NULL; } mps->need_sync = FALSE; mps->bitstream_start_pos = mps->header.header_pos; mps->stream_size = mps->bitstream->bitstream_size - mps->bitstream_start_pos;#else if( MPEGDEC_read_header( mps, (BOOL)ctrl->check_mpeg ) ) { // #6: check_mpeg (void)MPEGDEC_close( mpds ); return NULL; }#endif// #17 End // #13 Begin if( mps->header.layer < 3 ) dec_lay = &ctrl->layer_1_2; else dec_lay = &ctrl->layer_3; mps->force_mono = dec_lay->force_mono; if( mps->stereo ) dec_out = &dec_lay->stereo; else dec_out = &dec_lay->mono; freq_div = dec_out->freq_div; quality = dec_out->quality; freq_max = dec_out->freq_max; // #13 End#ifdef MPEGAUD_DEMO quality = 0;#endif if( freq_div == 0 ) { // #4 INT32 freq = mps->sfreq; mps->freq_div = 1; do { if( freq <= freq_max ) break; mps->freq_div <<= 1; freq >>= 1; } while ( mps->freq_div < 4 ); } else { mps->freq_div = freq_div; } switch( mps->freq_div ) { case 2: mps->sb_max = MPA_SBLIMIT/2; break; case 4: mps->sb_max = MPA_SBLIMIT/4; break; default: mps->freq_div = 1; mps->sb_max = MPA_SBLIMIT; break; } mps->quality = quality; if( mps->quality < MPEGDEC_QUALITY_LOW ) mps->quality = MPEGDEC_QUALITY_LOW; else if( mps->quality > MPEGDEC_QUALITY_HIGH ) mps->quality = MPEGDEC_QUALITY_HIGH; mps->mpegsub = MPEGSUB_open( mps->freq_div, mps->quality ); if( !mps->mpegsub ) { MPEGDEC_close( mpds ); return NULL; } /* #8 Begin */ mps->mpegimdct = MPEGIMDCT_open(); if( !mps->mpegimdct ) { MPEGDEC_close( mpds ); return NULL; } /* #8 End */ fill_info( mpds ); (void)BSTR_seek( mps->bitstream, /*0*/ mps->bitstream_start_pos ); // #17 decoder_reset( mpds ); return mpds;} /* MPEGDEC_open */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -