int FLAC_plugin__seek(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data)
{
	int pos;
	FLAC__uint64 target_sample = stream_data->total_samples * stream_data->seek_to / stream_data->length_in_msec;

	if (stream_data->total_samples > 0 && target_sample >= stream_data->total_samples && target_sample > 0)
		target_sample = stream_data->total_samples - 1;

	/* even if the seek fails we have to reset these so that we don't repeat the seek */
	stream_data->seek_to = -1;
	stream_data->eof = false;
	wide_samples_in_reservoir_ = 0;
	pos = (int)(target_sample*1000 / stream_data->sample_rate);

	if (!FLAC__stream_decoder_seek_absolute(decoder, target_sample)) {
		if(FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_SEEK_ERROR)
			FLAC__stream_decoder_flush(decoder);
		pos = -1;
	}

	bh_index_last_o = bh_index_last_w = (pos/BITRATE_HIST_SEGMENT_MSEC) % BITRATE_HIST_SIZE;
	if (!FLAC__stream_decoder_get_decode_position(decoder, &decode_position))
		decode_position = 0;

	return pos;
}
FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata *block, FLAC__bool *needs_write)
{
	FLAC__StreamDecoder *decoder;
	ClientData client_data;
	FLAC__bool ok = true;

	FLAC__ASSERT(0 != block);
	FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_SEEKTABLE);

	client_data.seektable_template = &block->data.seek_table;
	client_data.samples_written = 0;
	/* client_data.audio_offset must be determined later */
	client_data.first_seekpoint_to_check = 0;
	client_data.error_occurred = false;

	decoder = FLAC__stream_decoder_new();

	if(0 == decoder) {
		fprintf(stderr, "%s: ERROR (--add-seekpoint) creating the decoder instance\n", filename);
		return false;
	}

	FLAC__stream_decoder_set_md5_checking(decoder, false);
	FLAC__stream_decoder_set_metadata_ignore_all(decoder);

	if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, /*metadata_callback=*/0, error_callback_, &client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
		fprintf(stderr, "%s: ERROR (--add-seekpoint) initializing the decoder instance (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder));
		ok = false;
	}

	if(ok && !FLAC__stream_decoder_process_until_end_of_metadata(decoder)) {
		fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder));
		ok = false;
	}

	if(ok && !FLAC__stream_decoder_get_decode_position(decoder, &client_data.audio_offset)) {
		fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file\n", filename);
		ok = false;
	}
	client_data.last_offset = client_data.audio_offset;

	if(ok && !FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
		fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder));
		ok = false;
	}

	if(ok && client_data.error_occurred) {
		fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%u:%s)\n", filename, (unsigned)client_data.error_status, FLAC__StreamDecoderErrorStatusString[client_data.error_status]);
		ok = false;
	}

	*needs_write = true;
	FLAC__stream_decoder_delete(decoder);
	return ok;
}
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
	ClientData *cd = (ClientData*)client_data;

	(void)buffer;
	FLAC__ASSERT(0 != cd);

	if(!cd->error_occurred) {
		const unsigned blocksize = frame->header.blocksize;
		const FLAC__uint64 frame_first_sample = cd->samples_written;
		const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
		FLAC__uint64 test_sample;
		unsigned i;
		for(i = cd->first_seekpoint_to_check; i < cd->seektable_template->num_points; i++) {
			test_sample = cd->seektable_template->points[i].sample_number;
			if(test_sample > frame_last_sample) {
				break;
			}
			else if(test_sample >= frame_first_sample) {
				cd->seektable_template->points[i].sample_number = frame_first_sample;
				cd->seektable_template->points[i].stream_offset = cd->last_offset - cd->audio_offset;
				cd->seektable_template->points[i].frame_samples = blocksize;
				cd->first_seekpoint_to_check++;
				/* DO NOT: "break;" and here's why:
				 * The seektable template may contain more than one target
				 * sample for any given frame; we will keep looping, generating
				 * duplicate seekpoints for them, and we'll clean it up later,
				 * just before writing the seektable back to the metadata.
				 */
			}
			else {
				cd->first_seekpoint_to_check++;
			}
		}
		cd->samples_written += blocksize;
		if(!FLAC__stream_decoder_get_decode_position(decoder, &cd->last_offset))
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
		return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
	}
	else
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
Exemple #4
0
static FLAC__StreamDecoderWriteStatus
flac_write_cb(const FLAC__StreamDecoder *dec, const FLAC__Frame *frame,
	      const FLAC__int32 *const buf[], void *vdata)
{
	struct flac_data *data = (struct flac_data *) vdata;
	FLAC__uint64 nbytes = 0;

	if (FLAC__stream_decoder_get_decode_position(dec, &nbytes)) {
		if (data->position > 0 && nbytes > data->position) {
			nbytes -= data->position;
			data->position += nbytes;
		} else {
			data->position = nbytes;
			nbytes = 0;
		}
	} else
		nbytes = 0;

	return flac_common_write(data, frame, buf, nbytes);
}
Exemple #5
0
static size_t audiosourceflac_Position(struct audiosource* source) {
    struct audiosourceflac_internaldata* idata =
            source->internaldata;

    if (idata->eof && idata->returnerroroneof) {
        return 0;
    }
    if (!idata->flacopened) {
        return 0;
    }

    if (source->seekable) {
        uint64_t pos;
        if (FLAC__stream_decoder_get_decode_position(
                    idata->decoder, &pos) == true) {
            return pos;
        }
    }
    return 0;
}
Exemple #6
0
CBaseDec::RetCode CFlacDec::Decoder(FILE *in, const int /*OutputFd*/, State* const state, CAudioMetaData* meta_data, time_t* const time_played, unsigned int* const secondsToSkip)
{
	int rval;
//	FLAC__uint64 jumptime=0;
	Status = OK;
	mState = state;
	mTimePlayed = time_played;
	mFrameCount = 0;
	mSamplesProcessed = 0;
	struct stat s;
	FLAC__uint64 filesize = 0;

	mFlacDec = FLAC__stream_decoder_new();

	if (!Open(in, mFlacDec))
	{
		Status=DATA_ERR;
		return Status;
	}

	if (fstat(fileno(in), &s))
	{
		perror("CFlacDec::Decoder fstat");
		*time_played = 0;
	}
	else
		filesize = (FLAC__uint64)s.st_size;

	/* up and away ... */
	mSlotSize = MAX_OUTPUT_SAMPLES * 2 * FLAC__stream_decoder_get_channels(mFlacDec);
//	State oldstate=*state;
	int jumppos=0;
	int actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000;
	int bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8;
	int bytes_to_play = MSECS_TO_PLAY * meta_data->bitrate / 8000;
	unsigned int oldSecsToSkip = *secondsToSkip;
	FLAC__uint64 position;

	do
	{
		while(*state==PAUSE)
			usleep(10000);

		if(*state==FF || *state==REV)
		{
			if (oldSecsToSkip != *secondsToSkip)
			{
				actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000;
				bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8;
				oldSecsToSkip = *secondsToSkip;
			}
			printf("skipping %d secs and %d bytes\n",actSecsToSkip,bytes_to_skip);
			if(std::abs(ftell(in)-jumppos) > bytes_to_play)
			{
				if(*state==FF)
				{
					fseek(in, bytes_to_skip, SEEK_CUR);
					jumppos=ftell(in);
				}
				else
				{
					if(ftell(in) < bytes_to_skip)
					{
						fseek(in, 0, SEEK_SET);
						*state=PLAY;
					}
					else
					{
						fseek(in, -bytes_to_skip, SEEK_CUR);
						jumppos=ftell(in);
					}
				}
			}

			// if a custom value was set we only jump once
			if (*secondsToSkip != 0) {
				*state=PLAY;
			}
		}

		if (FLAC__stream_decoder_get_state(mFlacDec) == FLAC__STREAM_DECODER_END_OF_STREAM) {
			rval = false;
			break;
		}

		rval = FLAC__stream_decoder_process_single(mFlacDec);

		/* update playback position */
		if (filesize > 0 && FLAC__stream_decoder_get_decode_position(mFlacDec, &position))
			*time_played = position / 1000ULL * mLengthInMsec / filesize;

	} while (rval && *state != STOP_REQ && Status == OK);

	// let buffer run dry
	printf("let buffer run dry\n");
	while (rval == true && *state != STOP_REQ && Status == OK /* && mReadSlot != mWriteSlot*/)
	{
		printf("...drying - *state=%x, Status=%x\n", *state, Status);
		usleep(100000);
	}

	/* clean up the junk from the party */
	if (mMetadata)
		FLAC__metadata_object_delete(mMetadata);
	mMetadata = NULL;
	FLAC__stream_decoder_finish(mFlacDec);
	FLAC__stream_decoder_delete(mFlacDec);
	mFlacDec = NULL;

	audioDecoder->StopClip();

	/* and drive home ;) */
	return Status;
}
Exemple #7
0
bool
flac_reader_c::parse_file() {
  FLAC__StreamDecoderState state;
  flac_block_t block;
  uint64_t u, old_pos;
  int result, progress, old_progress;
  bool ok;

  m_in->setFilePointer(0);
  metadata_parsed = false;

  mxinfo(Y("+-> Parsing the FLAC file. This can take a LONG time.\n"));

  init_flac_decoder();
  result = FLAC__stream_decoder_process_until_end_of_metadata(m_flac_decoder.get());

  mxverb(2, boost::format("flac_reader: extract->metadata, result: %1%, mdp: %2%, num blocks: %3%\n") % result % metadata_parsed % blocks.size());

  if (!metadata_parsed)
    mxerror_fn(m_ti.m_fname, Y("No metadata block found. This file is broken.\n"));

  FLAC__stream_decoder_get_decode_position(m_flac_decoder.get(), &u);

  block.type    = FLAC_BLOCK_TYPE_HEADERS;
  block.filepos = 0;
  block.len     = u;
  old_pos       = u;

  blocks.push_back(block);

  mxverb(2, boost::format("flac_reader: headers: block at %1% with size %2%\n") % block.filepos % block.len);

  old_progress = -5;
  ok = FLAC__stream_decoder_skip_single_frame(m_flac_decoder.get());
  while (ok) {
    state = FLAC__stream_decoder_get_state(m_flac_decoder.get());

    progress = m_in->getFilePointer() * 100 / m_size;
    if ((progress - old_progress) >= 5) {
      mxinfo(boost::format(Y("+-> Pre-parsing FLAC file: %1%%%%2%")) % progress % "\r");
      old_progress = progress;
    }

    if (FLAC__stream_decoder_get_decode_position(m_flac_decoder.get(), &u) && (u != old_pos)) {
      block.type    = FLAC_BLOCK_TYPE_DATA;
      block.filepos = old_pos;
      block.len     = u - old_pos;
      old_pos       = u;
      blocks.push_back(block);

      mxverb(2, boost::format("flac_reader: skip/decode frame, block at %1% with size %2%\n") % block.filepos % block.len);
    }

    if (state > FLAC__STREAM_DECODER_READ_FRAME)
      break;

    ok = FLAC__stream_decoder_skip_single_frame(m_flac_decoder.get());
  }

  if (100 != old_progress)
    mxinfo(Y("+-> Pre-parsing FLAC file: 100%\n"));
  else
    mxinfo("\n");

  if ((blocks.size() == 0) || (blocks[0].type != FLAC_BLOCK_TYPE_HEADERS))
    mxerror(Y("flac_reader: Could not read all header packets.\n"));

  m_in->setFilePointer(0);
  blocks[0].len     -= 4;
  blocks[0].filepos  = 4;

  return metadata_parsed;
}
unsigned FLAC_plugin__decode(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data, char *sample_buffer)
{
	/* fill reservoir */
	while (wide_samples_in_reservoir_ < SAMPLES_PER_WRITE)
	{
		if (FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
		{
			stream_data->eof = true;
			break;
		}
		else if (!FLAC__stream_decoder_process_single(decoder))
		{
			FLAC_plugin__show_error("Error while processing frame (%s).", FLAC__stream_decoder_get_resolved_state_string(decoder));
			stream_data->eof = true;
			break;
		}
		if (!FLAC__stream_decoder_get_decode_position(decoder, &decode_position))
			decode_position = 0;
	}
	/* output samples */
	if (wide_samples_in_reservoir_ > 0)
	{
		const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE);
		const unsigned channels = stream_data->channels;
		unsigned i;
		int bytes;

		if (cfg.replaygain.enable && stream_data->has_replaygain)
		{
			bytes = FLAC__replaygain_synthesis__apply_gain(
				sample_buffer,
				true, /* little_endian_data_out */
				stream_data->output_bits_per_sample == 8, /* unsigned_data_out */
				reservoir__,
				n,
				channels,
				stream_data->bits_per_sample,
				stream_data->output_bits_per_sample,
				stream_data->replay_scale,
				cfg.replaygain.hard_limit,
				cfg.resolution.replaygain.dither,
				&stream_data->dither_context
			);
		}
		else
		{
			bytes = FLAC__plugin_common__pack_pcm_signed_little_endian(
				sample_buffer,
				reservoir__,
				n,
				channels,
				stream_data->bits_per_sample,
				stream_data->output_bits_per_sample
			);
		}

		wide_samples_in_reservoir_ -= n;
		for (i = 0; i < channels; i++)
			memmove(&reservoir_[i][0], &reservoir_[i][n], sizeof(reservoir_[0][0]) * wide_samples_in_reservoir_);

		return bytes;
	}
	else
	{
		stream_data->eof = true;
		return 0;
	}
}
Exemple #9
0
void *play_loop_(void *arg)
{
	unsigned written_time_last = 0, bh_index_last_w = 0, bh_index_last_o = BITRATE_HIST_SIZE, blocksize = 1;
	FLAC__uint64 decode_position_last = 0, decode_position_frame_last = 0, decode_position_frame = 0;

	(void)arg;

	while(stream_data_.is_playing) {
		if(!stream_data_.eof) {
			while(sample_buffer_last_ - sample_buffer_first_ < SAMPLES_PER_WRITE) {
				unsigned s;

				s = sample_buffer_last_ - sample_buffer_first_;
				if(FLAC__stream_decoder_get_state(decoder_) == FLAC__STREAM_DECODER_END_OF_STREAM) {
					stream_data_.eof = true;
					break;
				}
				else if(!FLAC__stream_decoder_process_single(decoder_)) {
					/*@@@ this should probably be a dialog */
					fprintf(stderr, "libxmms-flac: READ ERROR processing frame\n");
					stream_data_.eof = true;
					break;
				}
				blocksize = sample_buffer_last_ - sample_buffer_first_ - s;
				decode_position_frame_last = decode_position_frame;
				if(stream_data_.is_http_source || !FLAC__stream_decoder_get_decode_position(decoder_, &decode_position_frame))
					decode_position_frame = 0;
			}
			if(sample_buffer_last_ - sample_buffer_first_ > 0) {
				const unsigned n = min(sample_buffer_last_ - sample_buffer_first_, SAMPLES_PER_WRITE);
				int bytes = n * stream_data_.channels * stream_data_.sample_format_bytes_per_sample;
				FLAC__byte *sample_buffer_start = sample_buffer_ + sample_buffer_first_ * stream_data_.channels * stream_data_.sample_format_bytes_per_sample;
				unsigned written_time, bh_index_w;
				FLAC__uint64 decode_position;

				sample_buffer_first_ += n;
				flac_ip.add_vis_pcm(flac_ip.output->written_time(), stream_data_.sample_format, stream_data_.channels, bytes, sample_buffer_start);
				while(flac_ip.output->buffer_free() < (int)bytes && stream_data_.is_playing && stream_data_.seek_to_in_sec == -1)
					xmms_usleep(10000);
				if(stream_data_.is_playing && stream_data_.seek_to_in_sec == -1)
					flac_ip.output->write_audio(sample_buffer_start, bytes);

				/* compute current bitrate */

				written_time = flac_ip.output->written_time();
				bh_index_w = written_time / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE;
				if(bh_index_w != bh_index_last_w) {
					bh_index_last_w = bh_index_w;
					decode_position = decode_position_frame - (double)(sample_buffer_last_ - sample_buffer_first_) * (double)(decode_position_frame - decode_position_frame_last) / (double)blocksize;
					bitrate_history_[(bh_index_w + BITRATE_HIST_SIZE - 1) % BITRATE_HIST_SIZE] =
						decode_position > decode_position_last && written_time > written_time_last ?
							8000 * (decode_position - decode_position_last) / (written_time - written_time_last) :
							stream_data_.sample_rate * stream_data_.channels * stream_data_.bits_per_sample;
					decode_position_last = decode_position;
					written_time_last = written_time;
				}
			}
			else {
				stream_data_.eof = true;
				xmms_usleep(10000);
			}
		}
		else
			xmms_usleep(10000);
		if(!stream_data_.is_http_source && stream_data_.seek_to_in_sec != -1) {
			const double distance = (double)stream_data_.seek_to_in_sec * 1000.0 / (double)stream_data_.length_in_msec;
			FLAC__uint64 target_sample = (FLAC__uint64)(distance * (double)stream_data_.total_samples);
			if(stream_data_.total_samples > 0 && target_sample >= stream_data_.total_samples)
				target_sample = stream_data_.total_samples - 1;
			if(FLAC__stream_decoder_seek_absolute(decoder_, target_sample)) {
				flac_ip.output->flush(stream_data_.seek_to_in_sec * 1000);
				bh_index_last_w = bh_index_last_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE;
				if(!FLAC__stream_decoder_get_decode_position(decoder_, &decode_position_frame))
					decode_position_frame = 0;
				stream_data_.eof = false;
				sample_buffer_first_ = sample_buffer_last_ = 0;
			}
			else if(FLAC__stream_decoder_get_state(decoder_) == FLAC__STREAM_DECODER_SEEK_ERROR) {
				/*@@@ this should probably be a dialog */
				fprintf(stderr, "libxmms-flac: SEEK ERROR\n");
				FLAC__stream_decoder_flush(decoder_);
				stream_data_.eof = false;
				sample_buffer_first_ = sample_buffer_last_ = 0;
			}
			stream_data_.seek_to_in_sec = -1;
		}
		else {
			/* display the right bitrate from history */
			unsigned bh_index_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE;
			if(bh_index_o != bh_index_last_o && bh_index_o != bh_index_last_w && bh_index_o != (bh_index_last_w + 1) % BITRATE_HIST_SIZE) {
				bh_index_last_o = bh_index_o;
				flac_ip.set_info(stream_data_.title, stream_data_.length_in_msec, bitrate_history_[bh_index_o], stream_data_.sample_rate, stream_data_.channels);
			}
		}
	}

	safe_decoder_finish_(decoder_);

	/* are these two calls necessary? */
	flac_ip.output->buffer_free();
	flac_ip.output->buffer_free();

	g_free(stream_data_.title);

	pthread_exit(NULL);
	return 0; /* to silence the compiler warning about not returning a value */
}