int mp3dec_seek(mp3dec_t mp3dec, int64_t pos, int units) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)mp3dec; int64_t newpos; if (!mp3 || (mp3->size != sizeof(struct mp3dec_t)) || !mp3->mpadec) return MP3DEC_RETCODE_INVALID_HANDLE; if (!(mp3->flags & MP3DEC_FLAG_INITIALIZED)) return MP3DEC_RETCODE_BAD_STATE; if (!(mp3->flags & MP3DEC_FLAG_SEEKABLE)) return MP3DEC_RETCODE_SEEK_FAILED; if (units == MP3DEC_SEEK_BYTES) { newpos = (pos < mp3->stream_size) ? pos : mp3->stream_size; newpos = lseek(mp3->fd, mp3->stream_offset + newpos, SEEK_SET); if (newpos < 0) return MP3DEC_RETCODE_SEEK_FAILED; mp3->stream_position = newpos - mp3->stream_offset; mp3->in_buffer_offset = mp3->in_buffer_used = 0; mp3->out_buffer_offset = mp3->out_buffer_used = 0; } else if (units == MP3DEC_SEEK_SAMPLES) { MYFLT fsize = (MYFLT)(125.0*mp3->mpainfo.bitrate*mp3->mpainfo.decoded_frame_samples)/ (MYFLT)mp3->mpainfo.decoded_frequency; newpos = (int64_t) ((MYFLT)pos*fsize/(MYFLT)mp3->mpainfo.decoded_frame_samples); if (newpos > mp3->stream_size) newpos = mp3->stream_size; pos = (pos%mp3->mpainfo.decoded_frame_samples)* mp3->mpainfo.decoded_sample_size; newpos = lseek(mp3->fd, mp3->stream_offset + newpos, SEEK_SET); if (newpos < 0) return MP3DEC_RETCODE_SEEK_FAILED; mp3->stream_position = newpos - mp3->stream_offset; mp3->in_buffer_offset = mp3->in_buffer_used = 0; mp3->out_buffer_offset = mp3->out_buffer_used = 0; { uint8_t temp[8*1152]; mp3dec_decode(mp3, temp, (uint32_t)pos, NULL); } } else if (units == MP3DEC_SEEK_SECONDS) { if (pos > mp3->mpainfo.duration) pos = mp3->mpainfo.duration; if (mp3->taginfo.flags & 4) { int32_t n = (int32_t)((100*pos + (mp3->mpainfo.duration >> 1))/ mp3->mpainfo.duration); if (n > 99) newpos = mp3->stream_size; else newpos = (mp3->taginfo.toc[n]*mp3->stream_size)/255; } else newpos =
void * startDecodeThread(void *url) { LogMessage(&gMain, LOG_DEBUG, "Starting decode thread"); char currentMetadata[2046] = ""; if (sourceMedia == MP3_FORMAT) { /* MP3 */ mp3dec_init(&mp3Decoder); } if (sourceMedia == OGGVORBIS_FORMAT) { /* Ogg Vorbis */ devorb_init (&vorbisDecoder); } decoderLoop = 1; while (decoderLoop) { int read = 0; long inbuffer = 0; char *pStreamData = NULL; inbuffer = cbuffer_get_used(&sourceCBuffer); if (decoderLoop) { if (inbuffer > 0) { pStreamData = (char*)malloc(inbuffer); if (cbuffer_extract(&sourceCBuffer, pStreamData, inbuffer)) { // fprintf(stdout, "Extracted %d from the circular buffer\n", inbuffer); pthread_mutex_lock(&encoders_mutex); if (sourceMedia == MP3_FORMAT) { mp3dec_feed_stream(&mp3Decoder, pStreamData, inbuffer); if (mp3dec_get_stream_size(&mp3Decoder) > MIN_MP3_STREAM_SIZE) { if (!mp3dec_decode(&mp3Decoder)) { pthread_mutex_unlock(&encoders_mutex); LogMessage(&gMain, LOG_ERROR, "Problem with mp3 decoding."); pthread_exit((void *)1); return 0; } } /* MP3 */ } if (sourceMedia == OGGVORBIS_FORMAT) { /* Vorbis */ devorb_read (&vorbisDecoder, pStreamData, inbuffer); while (devorb_decode (&vorbisDecoder)) { if (vorbisDecoder.headers_changed) { char StreamTitle[2046] = ""; char Artist[1024] = ""; char Title[1024] = ""; char **ptr=vorbisDecoder.vc.user_comments; while(*ptr){ char *pData = *ptr; if (!strncasecmp(pData, "ARTIST=", strlen("ARTIST="))) { strncpy(Artist, pData + strlen("ARTIST="), sizeof(Artist)-1); } if (!strncasecmp(pData, "TITLE=", strlen("TITLE="))) { strncpy(Title, pData + strlen("TITLE="), sizeof(Title)-1); } ++ptr; } sprintf(StreamTitle, "%s - %s", Artist, Title); inputMetadataCallback(&gMain, StreamTitle); for(int i = 0; i < gMain.gNumEncoders; i++) { setCurrentSongTitle(g[i], StreamTitle); } vorbisDecoder.headers_changed = 0; } } } pthread_mutex_unlock(&encoders_mutex); } if (pStreamData) { free(pStreamData); } } else { #ifdef WIN32 Sleep(100); #else usleep(250); #endif } } } LogMessage(&gMain, LOG_DEBUG, "Breaking out of decoder loop."); pthread_exit((void *)1); return 0; }