Пример #1
0
static FLAC__StreamDecoderWriteStatus write_cb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
											   const FLAC__int32 *const buffer[], void *client_data) {

	size_t frames = frame->header.blocksize;
	unsigned bits_per_sample = frame->header.bits_per_sample;
	unsigned channels = frame->header.channels;

	FLAC__int32 *lptr = (FLAC__int32 *)buffer[0];
	FLAC__int32 *rptr = (FLAC__int32 *)buffer[channels > 1 ? 1 : 0];
	
	if (decode.new_stream) {
		LOCK_O;
		LOG_INFO("setting track_start");
		output.track_start = outputbuf->writep;
		decode.new_stream = false;

#if DSD
		if (output.has_dop && bits_per_sample == 24 && is_flac_dop((u32_t *)lptr, (u32_t *)rptr, frames)) {
			LOG_INFO("file contains DOP");
			output.next_dop = true;
			output.next_sample_rate = frame->header.sample_rate;
			output.fade = FADE_INACTIVE;
		} else {
			output.next_sample_rate = decode_newstream(frame->header.sample_rate, output.supported_rates);
			output.next_dop = false;
			if (output.fade_mode) _checkfade(true);
		}
#else
		output.next_sample_rate = decode_newstream(frame->header.sample_rate, output.supported_rates);
		if (output.fade_mode) _checkfade(true);
#endif

		UNLOCK_O;
	}

	LOCK_O_direct;

	while (frames > 0) {
		frames_t f;
		frames_t count;
		s32_t *optr;

		IF_DIRECT( 
			optr = (s32_t *)outputbuf->writep; 
			f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME; 
		);
		IF_PROCESS(
			optr = (s32_t *)process.inbuf;
			f = process.max_in_frames;
		);
Пример #2
0
static FLAC__StreamDecoderWriteStatus write_cb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
											   const FLAC__int32 *const buffer[], void *client_data) {

	size_t frames = frame->header.blocksize;
	unsigned bits_per_sample = frame->header.bits_per_sample;
	unsigned channels = frame->header.channels;

	FLAC__int32 *lptr = (FLAC__int32 *)buffer[0];
	FLAC__int32 *rptr = (FLAC__int32 *)buffer[channels > 1 ? 1 : 0];
	
	if (decode.new_stream) {
		LOCK_O;
		LOG_INFO("setting track_start");
		output.next_sample_rate = decode_newstream(frame->header.sample_rate, output.max_sample_rate);
		output.track_start = outputbuf->writep;
		if (output.fade_mode) _checkfade(true);
		decode.new_stream = false;
		UNLOCK_O;
	}

	LOCK_O_direct;

	while (frames > 0) {
		frames_t f;
		frames_t count;
		s32_t *optr;

		IF_DIRECT( 
			optr = (s32_t *)outputbuf->writep; 
			f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME; 
		);
		IF_PROCESS(
			optr = (s32_t *)process.inbuf;
			f = process.max_in_frames;
		);
Пример #3
0
static decode_state faad_decode(void) {
	size_t bytes_total;
	size_t bytes_wrap;
	NeAACDecFrameInfo info;
	s32_t *iptr;
	bool endstream;
	frames_t frames;

	LOCK_S;
	bytes_total = _buf_used(streambuf);
	bytes_wrap  = min(bytes_total, _buf_cont_read(streambuf));

	if (stream.state <= DISCONNECT && !bytes_total) {
		UNLOCK_S;
		return DECODE_COMPLETE;
	}

	if (a->consume) {
		u32_t consume = min(a->consume, bytes_wrap);
		LOG_DEBUG("consume: %u of %u", consume, a->consume);
		_buf_inc_readp(streambuf, consume);
		a->pos += consume;
		a->consume -= consume;
		UNLOCK_S;
		return DECODE_RUNNING;
	}

	if (decode.new_stream) {
		int found = 0;
		static unsigned char channels;
		static unsigned long samplerate;

		if (a->type == '2') {

			// adts stream - seek for header
			while (bytes_wrap >= 2 && (*(streambuf->readp) != 0xFF || (*(streambuf->readp + 1) & 0xF6) != 0xF0)) {
				_buf_inc_readp(streambuf, 1);
				bytes_total--;
				bytes_wrap--;
			}
			
			if (bytes_wrap >= 2) {
				long n = NEAAC(a, Init, a->hAac, streambuf->readp, bytes_wrap, &samplerate, &channels);
				if (n < 0) {
					found = -1;
				} else {
					_buf_inc_readp(streambuf, n);
					found = 1;
				}
			}

		} else {

			// mp4 - read header
			found = read_mp4_header(&samplerate, &channels);
		}

		if (found == 1) {

			LOG_INFO("samplerate: %u channels: %u", samplerate, channels);
			bytes_total = _buf_used(streambuf);
			bytes_wrap  = min(bytes_total, _buf_cont_read(streambuf));

			LOCK_O;
			LOG_INFO("setting track_start");
			output.next_sample_rate = decode_newstream(samplerate, output.supported_rates);
			IF_DSD( output.next_dop = false; )
Пример #4
0
static decode_state faad_decode(void) {
	size_t bytes_total;
	size_t bytes_wrap;
	NeAACDecFrameInfo info;
	s32_t *iptr;
	bool endstream;
	frames_t frames;

	LOCK_S;
	bytes_total = _buf_used(streambuf);
	bytes_wrap  = min(bytes_total, _buf_cont_read(streambuf));

	if (stream.state <= DISCONNECT && !bytes_total) {
		UNLOCK_S;
		return DECODE_COMPLETE;
	}

	if (a->consume) {
		u32_t consume = min(a->consume, bytes_wrap);
		LOG_DEBUG("consume: %u of %u", consume, a->consume);
		_buf_inc_readp(streambuf, consume);
		a->pos += consume;
		a->consume -= consume;
		UNLOCK_S;
		return DECODE_RUNNING;
	}

	if (decode.new_stream) {
		int found = 0;
		static unsigned char channels;
		static unsigned long samplerate;

		if (a->type == '2') {

			// adts stream - seek for header
			while (bytes_wrap >= 2 && (*(streambuf->readp) != 0xFF || (*(streambuf->readp + 1) & 0xF6) != 0xF0)) {
				_buf_inc_readp(streambuf, 1);
				bytes_total--;
				bytes_wrap--;
			}
			
			if (bytes_wrap >= 2) {
				long n = NEAAC(a, Init, a->hAac, streambuf->readp, bytes_wrap, &samplerate, &channels);
				if (n < 0) {
					found = -1;
				} else {
					_buf_inc_readp(streambuf, n);
					found = 1;
				}
			}

		} else {

			// mp4 - read header
			found = read_mp4_header(&samplerate, &channels);
		}

		if (found == 1) {

			LOG_INFO("samplerate: %u channels: %u", samplerate, channels);
			bytes_total = _buf_used(streambuf);
			bytes_wrap  = min(bytes_total, _buf_cont_read(streambuf));

			LOCK_O;
			LOG_INFO("setting track_start");
			output.next_sample_rate = decode_newstream(samplerate, output.max_sample_rate);
			output.track_start = outputbuf->writep;
			if (output.fade_mode) _checkfade(true);
			decode.new_stream = false;
			UNLOCK_O;

		} else if (found == -1) {

			LOG_WARN("error reading stream header");
			UNLOCK_S;
			return DECODE_ERROR;

		} else {

			// not finished header parsing come back next time
			UNLOCK_S;
			return DECODE_RUNNING;
		}
	}

	if (bytes_wrap < WRAPBUF_LEN && bytes_total > WRAPBUF_LEN) {

		// make a local copy of frames which may have wrapped round the end of streambuf
		u8_t buf[WRAPBUF_LEN];
		memcpy(buf, streambuf->readp, bytes_wrap);
		memcpy(buf + bytes_wrap, streambuf->buf, WRAPBUF_LEN - bytes_wrap);

		iptr = NEAAC(a, Decode, a->hAac, &info, buf, WRAPBUF_LEN);

	} else {

		iptr = NEAAC(a, Decode, a->hAac, &info, streambuf->readp, bytes_wrap);
	}

	if (info.error) {
		LOG_WARN("error: %u %s", info.error, NEAAC(a, GetErrorMessage, info.error));
	}

	endstream = false;

	// mp4 end of chunk - skip to next offset
	if (a->chunkinfo && a->chunkinfo[a->nextchunk].offset && a->sample++ == a->chunkinfo[a->nextchunk].sample) {

		if (a->chunkinfo[a->nextchunk].offset > a->pos) {
			u32_t skip = a->chunkinfo[a->nextchunk].offset - a->pos;
			if (skip != info.bytesconsumed) {
				LOG_DEBUG("skipping to next chunk pos: %u consumed: %u != skip: %u", a->pos, info.bytesconsumed, skip);
			}
			if (bytes_total >= skip) {
				_buf_inc_readp(streambuf, skip);
				a->pos += skip;
			} else {
				a->consume = skip;
			}
			a->nextchunk++;
		} else {
			LOG_ERROR("error: need to skip backwards!");
			endstream = true;
		}

	// adts and mp4 when not at end of chunk 
	} else if (info.bytesconsumed != 0) {

		_buf_inc_readp(streambuf, info.bytesconsumed);
		a->pos += info.bytesconsumed;

	// error which doesn't advance streambuf - end
	} else {
		endstream = true;
	}

	UNLOCK_S;

	if (endstream) {
		LOG_WARN("unable to decode further");
		return DECODE_ERROR;
	}

	if (!info.samples) {
		a->empty = true;
		return DECODE_RUNNING;
	}

	frames = info.samples / info.channels;

	if (a->skip) {
		u32_t skip;
		if (a->empty) {
			a->empty = false;
			a->skip -= frames;
			LOG_DEBUG("gapless: first frame empty, skipped %u frames at start", frames);
		}
		skip = min(frames, a->skip);
		LOG_DEBUG("gapless: skipping %u frames at start", skip);
		frames -= skip;
		a->skip -= skip;
		iptr += skip * info.channels;
	}

	if (a->samples) {
		if (a->samples < frames) {
			LOG_DEBUG("gapless: trimming %u frames from end", frames - a->samples);
			frames = (frames_t)a->samples;
		}
		a->samples -= frames;
	}

	LOG_SDEBUG("write %u frames", frames);

	LOCK_O_direct;

	while (frames > 0) {
		frames_t f;
		frames_t count;
		s32_t *optr;

		IF_DIRECT(
			f = _buf_cont_write(outputbuf) / BYTES_PER_FRAME;
			optr = (s32_t *)outputbuf->writep;
		);
		IF_PROCESS(
			f = process.max_in_frames;
			optr = (s32_t *)process.inbuf;
		);
Пример #5
0
static decode_state ff_decode(void) {
	int r, len, got_frame;
	AVPacket pkt_c;
	s32_t *optr = NULL;

	if (decode.new_stream) {

		AVIOContext *avio;
		AVStream *av_stream;
		AVCodec *codec;
		int o;
		int audio_stream = -1;

		ff->mmsh_bytes_left = ff->mmsh_bytes_pad = ff->mmsh_packet_len = 0;

		if (!ff->readbuf) {
			ff->readbuf = AV(ff, malloc, READ_SIZE +  FF_INPUT_BUFFER_PADDING_SIZE);
		}

		avio = AVIO(ff, alloc_context, ff->readbuf, READ_SIZE, 0, NULL, _read_data, NULL, NULL);
		avio->seekable = 0;

		ff->formatC = AVFORMAT(ff, alloc_context);
		if (ff->formatC == NULL) {
			LOG_ERROR("null context");
			return DECODE_ERROR;
		}

		ff->formatC->pb = avio;
		ff->formatC->flags |= AVFMT_FLAG_CUSTOM_IO | AVFMT_FLAG_NOPARSE;

		o = AVFORMAT(ff, open_input, &ff->formatC, "", ff->input_format, NULL);
		if (o < 0) {
			LOG_WARN("avformat_open_input: %d %s", o, av__err2str(o));
			return DECODE_ERROR;
		}

		LOG_INFO("format: name:%s lname:%s", ff->formatC->iformat->name, ff->formatC->iformat->long_name);
	
		o = AVFORMAT(ff, find_stream_info, ff->formatC, NULL);
		if (o < 0) {
			LOG_WARN("avformat_find_stream_info: %d %s", o, av__err2str(o));
			return DECODE_ERROR;
		}
		
		if (ff->wma && ff->wma_playstream < ff->formatC->nb_streams) {
			if (ff->formatC->streams[ff->wma_playstream]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
				LOG_INFO("using wma stream sent from server: %i", ff->wma_playstream);
				audio_stream = ff->wma_playstream;
			}
		}

		if (audio_stream == -1) {
			int i;
			for (i = 0; i < ff->formatC->nb_streams; ++i) {
				if (ff->formatC->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
					audio_stream = i;
					LOG_INFO("found stream: %i", i);
					break;
				}
			}
		}

		if (audio_stream == -1) {
			LOG_WARN("no audio stream found");
			return DECODE_ERROR;
		}

		av_stream = ff->formatC->streams[audio_stream];

		ff->codecC = av_stream->codec;

		codec = AVCODEC(ff, find_decoder, ff->codecC->codec_id);

		AVCODEC(ff, open2, ff->codecC, codec, NULL);

		ff->frame = AVCODEC(ff, alloc_frame);

		ff->avpkt = AV(ff, malloc, sizeof(AVPacket));
		if (ff->avpkt == NULL) {
			LOG_ERROR("can't allocate avpkt");
			return DECODE_ERROR;
		}

		AV(ff, init_packet, ff->avpkt);
		ff->avpkt->data = NULL;
		ff->avpkt->size = 0;

		LOCK_O;
		LOG_INFO("setting track_start");
		output.next_sample_rate = decode_newstream(ff->codecC->sample_rate, output.max_sample_rate);
		output.track_start = outputbuf->writep;
		if (output.fade_mode) _checkfade(true);
		decode.new_stream = false;
		UNLOCK_O;
	}

	got_frame = 0;

	if ((r = AV(ff, read_frame, ff->formatC, ff->avpkt)) < 0) {
		if (r == AVERROR_EOF) {
			if (ff->end_of_stream) {
				LOG_INFO("decode complete");
				return DECODE_COMPLETE;
			} else {
				LOG_INFO("codec end of file");
			}
		} else {
			LOG_ERROR("av_read_frame error: %i %s", r, av__err2str(r));
		}
		return DECODE_RUNNING;
	}

	// clone packet as we are adjusting it
	pkt_c = *ff->avpkt;

	IF_PROCESS(
		optr = (s32_t *)process.inbuf;
		process.in_frames = 0;
	);