int mpeg_tell(int fd, int *pos, int *len) { int rv = -1; if((handle != NULL) && (fd != -1)) { off_t sample_off = 0; off_t frame_off = 0; double time_off = 0; double time_per_frame = 0; int samples_per_frame = 0; time_per_frame = mpg123_tpf(handle->mh); samples_per_frame = mpg123_spf(handle->mh); /* Determine current position */ frame_off = mpg123_tellframe(handle->mh); time_off = frame_off * (double)time_per_frame; *pos = (int) time_off; /* Determine track duration */ sample_off = mpg123_length(handle->mh); if(samples_per_frame != 0) { frame_off = sample_off / samples_per_frame; time_off = frame_off * (double)time_per_frame; *len = (int) time_off; } rv = 0; } return rv; }
int mp3file_determineStats(MP3File *mp3) { if (mp3 == NULL) return; int encoding; mpg123_handle* mh = mp3->handle; int err = mpg123_getformat(mh, &mp3->rate, &mp3->channels, &encoding); if (err == MPG123_NEED_MORE) return err; if (err != MPG123_OK) { printerr("mpg123_getformat", err); return err; } mpg123_format_none(mh); mpg123_format(mh, mp3->rate, mp3->channels, encoding); mp3->num_samples = mpg123_length(mh); mp3->samples_per_frame = mpg123_spf(mh); mp3->secs_per_frame = mpg123_tpf(mh); if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0) mp3->num_frames = 0; else mp3->num_frames = mp3->num_samples / mp3->samples_per_frame; if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0 || mp3->secs_per_frame < 0) mp3->duration = 0; else mp3->duration = mp3->num_samples / mp3->samples_per_frame * mp3->secs_per_frame; return err; }
JNIEXPORT void JNICALL Java_com_axelby_mp3decoders_MPG123_feed (JNIEnv *env, jclass c, jlong handle, jbyteArray in_buffer, jint in_size) { MP3File *mp3 = (MP3File*)handle; mpg123_handle *mh = mp3->handle; jboolean isCopy; jbyte* b = (*env)->GetByteArrayElements(env, in_buffer, &isCopy); int err = mpg123_feed(mh, b, in_size); if (err != MPG123_OK) __android_log_print(ANDROID_LOG_INFO, "podax-jni", "mpg123_feed error: %s", mpg123_plain_strerror(err)); (*env)->ReleaseByteArrayElements(env, in_buffer, b, JNI_ABORT); if (mp3->rate == 0) { off_t frame_offset; unsigned char* audio; size_t bytes_done; err = mpg123_decode_frame(mh, &frame_offset, &audio, &bytes_done); if (err == MPG123_NEW_FORMAT) { int encoding; err = mpg123_getformat(mh, &mp3->rate, &mp3->channels, &encoding); if (err != MPG123_NEED_MORE && err != MPG123_OK) { printerr("mpg123_getformat", err); return; } mp3->samples_per_frame = mpg123_spf(mh); mp3->secs_per_frame = mpg123_tpf(mh); } if (err != MPG123_OK && err != MPG123_NEED_MORE) __android_log_print(ANDROID_LOG_INFO, "podax-jni", "cannot get rate: %s", mpg123_plain_strerror(err)); } }
JNIEXPORT jlong JNICALL Java_com_axelby_podax_player_MPG123_openFile (JNIEnv *env, jclass c, jstring filename) { int err = MPG123_OK; mpg123_handle *mh = mpg123_new(NULL, &err); if (err == MPG123_OK && mh != NULL) { MP3File* mp3 = mp3file_init(mh); const char* fileString = (*env)->GetStringUTFChars(env, filename, NULL); err = mpg123_open(mh, fileString); (*env)->ReleaseStringUTFChars(env, filename, fileString); if (err == MPG123_OK) { int encoding; if (mpg123_getformat(mh, &mp3->rate, &mp3->channels, &encoding) == MPG123_OK) { if(encoding == MPG123_ENC_SIGNED_16) { // Signed 16 is the default output format anyway; // it would actually by only different if we forced it. // So this check is here just for this explanation. // Ensure that this output format will not change // (it could, when we allow it). mpg123_format_none(mh); mpg123_format(mh, mp3->rate, mp3->channels, encoding); mp3->buffer_size = mpg123_outblock(mh); mp3->buffer = (unsigned char*)malloc(mp3->buffer_size); mp3->num_samples = mpg123_length(mh); mp3->samples_per_frame = mpg123_spf(mh); mp3->secs_per_frame = mpg123_tpf(mh); if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0) mp3->num_frames = 0; else mp3->num_frames = mp3->num_samples / mp3->samples_per_frame; if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0 || mp3->secs_per_frame < 0) mp3->duration = 0; else mp3->duration = mp3->num_samples / mp3->samples_per_frame * mp3->secs_per_frame; return (jlong)mp3; } } } mp3file_delete(mp3); } else { __android_log_write(ANDROID_LOG_INFO, "podax-jni", mpg123_plain_strerror(err)); } return 0; }
VALUE rb_mpg123_spf(VALUE self) { return rb_float_new(mpg123_spf(DATA_PTR(self))); }
/**************************************************************************** * DecodeBlock: the whole thing ****************************************************************************/ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { int i_err; block_t *p_block = pp_block ? *pp_block : NULL; decoder_sys_t *p_sys = p_dec->p_sys; if( !pp_block || !p_block ) return NULL; if( p_block->i_buffer == 0 ) return NULL; if( !date_Get( &p_sys->end_date ) && p_block->i_pts <= VLC_TS_INVALID ) { /* We've just started the stream, wait for the first PTS. */ msg_Dbg( p_dec, "waiting for PTS" ); goto error; } if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) ) { date_Set( &p_sys->end_date, 0 ); if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) goto error; } /* Feed mpg123 with raw data */ i_err = mpg123_feed( p_sys->p_handle, p_block->p_buffer, p_block->i_buffer ); if( i_err != MPG123_OK ) { msg_Err( p_dec, "mpg123_feed failed: %s", mpg123_plain_strerror( i_err ) ); goto error; } /* Get details about the stream */ i_err = mpg123_info( p_sys->p_handle, &p_sys->frame_info ); if( i_err == MPG123_NEED_MORE ) { /* Need moar data */ goto error; } else if( i_err != MPG123_OK ) { msg_Err( p_dec, "mpg123_info failed: %s", mpg123_plain_strerror( i_err ) ); goto error; } /* Configure the output */ p_block->i_nb_samples = mpg123_spf( p_sys->p_handle ); p_dec->fmt_out.i_bitrate = p_sys->frame_info.bitrate * 1000; switch( p_sys->frame_info.mode ) { case MPG123_M_STEREO: case MPG123_M_JOINT: p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; break; case MPG123_M_DUAL: p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_DUALMONO; break; case MPG123_M_MONO: p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_CENTER; break; default: msg_Err( p_dec, "Unknown mode"); goto error; } p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels & AOUT_CHAN_PHYSMASK; /* Date management */ if( p_dec->fmt_out.audio.i_rate != p_sys->frame_info.rate ) { p_dec->fmt_out.audio.i_rate = p_sys->frame_info.rate; date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); date_Set( &p_sys->end_date, 0 ); } if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } /* Request a new audio buffer */ block_t *p_out = decoder_NewAudioBuffer( p_dec, p_block->i_nb_samples ); if( unlikely( !p_out ) ) goto error; /* Configure the buffer */ p_out->i_nb_samples = p_block->i_nb_samples; p_out->i_dts = p_out->i_pts = date_Get( &p_sys->end_date ); p_out->i_length = date_Increment( &p_sys->end_date, p_block->i_nb_samples ) - p_out->i_pts; /* Make mpg123 write directly into the VLC output buffer */ i_err = mpg123_replace_buffer( p_sys->p_handle, p_out->p_buffer, p_out->i_buffer ); if( i_err != MPG123_OK ) { msg_Err( p_dec, "could not replace buffer: %s", mpg123_plain_strerror( i_err ) ); block_Release( p_out ); goto error; } *pp_block = NULL; /* avoid being fed the same packet again */ /* Do the actual decoding now */ i_err = mpg123_decode_frame( p_sys->p_handle, NULL, NULL, NULL ); if( i_err != MPG123_OK ) { if( i_err != MPG123_NEW_FORMAT ) msg_Err( p_dec, "mpg123_decode_frame error: %s", mpg123_plain_strerror( i_err ) ); block_Release( p_out ); goto error; } block_Release( p_block ); return p_out; error: block_Release( p_block ); return NULL; }